1 /*****************************************************************************/
5 /* CPU core for the 6502 simulator */
9 /* (C) 2002 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@cc65.org */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
50 /*****************************************************************************/
52 /*****************************************************************************/
57 unsigned char AC; /* Accumulator */
58 unsigned char XR; /* X register */
59 unsigned char YR; /* Y register */
60 unsigned char SR; /* Status register */
61 unsigned char SP; /* Stackpointer */
62 unsigned PC; /* Program counter */
64 /* Count the total number of cylcles */
65 unsigned Cycles; /* Cycles per insn */
66 unsigned long TotalCycles; /* Total cycles */
68 /* Allow the stack page to be changed */
69 static unsigned StackPage = 0x100;
71 /* Status register bits */
72 #define CF 0x01 /* Carry flag */
73 #define ZF 0x02 /* Zero flag */
74 #define IF 0x04 /* Interrupt flag */
75 #define DF 0x08 /* Decimal flag */
76 #define BF 0x10 /* Break flag */
77 #define OF 0x40 /* Overflow flag */
78 #define SF 0x80 /* Sign flag */
85 /*****************************************************************************/
86 /* Helper functions and macros */
87 /*****************************************************************************/
92 #define SET_CF() (SR |= CF)
93 #define SET_ZF() (SR |= ZF)
94 #define SET_IF() (SR |= IF)
95 #define SET_DF() (SR |= DF)
96 #define SET_BF() (SR |= BF)
97 #define SET_OF() (SR |= OF)
98 #define SET_SF() (SR |= SF)
101 #define CLR_CF() (SR &= ~CF)
102 #define CLR_ZF() (SR &= ~ZF)
103 #define CLR_IF() (SR &= ~IF)
104 #define CLR_DF() (SR &= ~DF)
105 #define CLR_BF() (SR &= ~BF)
106 #define CLR_OF() (SR &= ~OF)
107 #define CLR_SF() (SR &= ~SF)
109 /* Test for the flags */
110 #define CF_IS_SET() (SR & CF)
111 #define ZF_IS_SET() (SR & ZF)
112 #define IF_IS_SET() (SR & IF)
113 #define DF_IS_SET() (SR & DF)
114 #define BF_IS_SET() (SR & BF)
115 #define OF_IS_SET() (SR & OF)
116 #define SF_IS_SET() (SR & SF)
118 /* Set the flags according to a given value */
119 #define TEST_ZF(v) do { if ((v) == 0) { SET_ZF(); } else { CLR_ZF(); } } while (0)
120 #define TEST_SF(v) do { if ((v) & 0x80) { SET_SF(); } else { CLR_SF(); } } while (0)
121 #define TEST_CF(v) do { if (v) { SET_CF (); } else { CLR_CF (); } } while (0)
123 /* Program counter halves */
124 #define PCL (PC & 0xFF)
125 #define PCH ((PC >> 8) & 0xFF)
127 /* Stack operations */
128 #define PUSH(Val) WriteMem (StackPage + SP--, Val)
129 #define POP() ReadMem (StackPage + ++SP)
131 /* Test for page cross */
132 #define PAGE_CROSS(addr,offs) ((((addr) & 0xFF) + offs) >= 0x100)
135 #define AC_OP_IMM(op) \
137 AC = AC op ReadMem (PC+1); \
143 #define AC_OP_ZP(op) \
145 AC = AC op ReadMem (ReadMem (PC+1)); \
151 #define AC_OP_ZPX(op) \
152 unsigned char ZPAddr; \
154 ZPAddr = ReadMem (PC+1) + XR; \
155 AC = AC op ReadMem (ZPAddr); \
161 #define AC_OP_ZPY(op) \
162 unsigned char ZPAddr; \
164 ZPAddr = ReadMem (PC+1) + YR; \
165 AC = AC op ReadMem (ZPAddr); \
171 #define AC_OP_ABS(op) \
174 Addr = ReadMemW (PC+1); \
175 AC = AC op ReadMem (Addr); \
181 #define AC_OP_ABSX(op) \
184 Addr = ReadMemW (PC+1); \
185 if (PAGE_CROSS (Addr, XR)) { \
188 AC = AC | ReadMem (Addr + XR); \
194 #define AC_OP_ABSY(op) \
197 Addr = ReadMemW (PC+1); \
198 if (PAGE_CROSS (Addr, YR)) { \
201 AC = AC | ReadMem (Addr + YR); \
207 #define AC_OP_ZPXIND(op) \
208 unsigned char ZPAddr; \
211 ZPAddr = ReadMem (PC+1) + XR; \
212 Addr = ReadZeroPageW (ZPAddr); \
213 AC = AC op ReadMem (Addr); \
219 #define AC_OP_ZPINDY(op) \
220 unsigned char ZPAddr; \
223 ZPAddr = ReadMem (PC+1); \
224 Addr = ReadZeroPageW (ZPAddr) + YR; \
225 AC = AC op ReadMem (Addr); \
231 #define BRANCH(cond) \
235 unsigned char OldPCH; \
237 Offs = (signed char) ReadMem (PC+1); \
240 if (PCH != OldPCH) { \
250 unsigned Result = v1 - v2; \
251 TEST_ZF (Result & 0xFF); \
253 TEST_CF (Result <= 0xFF); \
258 /*****************************************************************************/
259 /* Helper functions */
260 /*****************************************************************************/
264 static void Illegal (void)
266 fprintf (stderr, "Illegal: $%02X\n", ReadMem (PC));
272 static void NotImplemented (void)
274 fprintf (stderr, "Not implemented: $%02X\n", ReadMem (PC));
280 /*****************************************************************************/
282 /*****************************************************************************/
286 static void OPC_6502_00 (void)
287 /* Opcode $00: BRK */
296 PC = ReadMemW (0xFFFE);
301 static void OPC_6502_01 (void)
302 /* Opcode $01: ORA (ind,x) */
309 static void OPC_6502_02 (void)
317 static void OPC_6502_03 (void)
325 static void OPC_6502_04 (void)
333 static void OPC_6502_05 (void)
334 /* Opcode $05: ORA zp */
341 static void OPC_6502_06 (void)
342 /* Opcode $06: ASL zp */
349 static void OPC_6502_07 (void)
357 static void OPC_6502_08 (void)
358 /* Opcode $08: PHP */
367 static void OPC_6502_09 (void)
368 /* Opcode $09: ORA #imm */
375 static void OPC_6502_0A (void)
376 /* Opcode $0A: ASL a */
383 static void OPC_6502_0B (void)
391 static void OPC_6502_0C (void)
399 static void OPC_6502_0D (void)
400 /* Opcode $0D: ORA abs */
407 static void OPC_6502_0E (void)
408 /* Opcode $0E: ALS abs */
415 static void OPC_6502_0F (void)
423 static void OPC_6502_10 (void)
424 /* Opcode $10: BPL */
426 BRANCH (!SF_IS_SET ());
431 static void OPC_6502_11 (void)
432 /* Opcode $11: ORA (zp),y */
439 static void OPC_6502_12 (void)
447 static void OPC_6502_13 (void)
455 static void OPC_6502_14 (void)
463 static void OPC_6502_15 (void)
464 /* Opcode $15: ORA zp,x */
471 static void OPC_6502_16 (void)
472 /* Opcode $16: ASL zp,x */
479 static void OPC_6502_17 (void)
487 static void OPC_6502_18 (void)
488 /* Opcode $18: CLC */
497 static void OPC_6502_19 (void)
498 /* Opcode $19: ORA abs,y */
505 static void OPC_6502_1A (void)
513 static void OPC_6502_1B (void)
521 static void OPC_6502_1C (void)
529 static void OPC_6502_1D (void)
530 /* Opcode $1D: ORA abs,x */
537 static void OPC_6502_1E (void)
538 /* Opcode $1E: ASL abs,x */
545 static void OPC_6502_1F (void)
553 static void OPC_6502_20 (void)
554 /* Opcode $20: JSR */
561 static void OPC_6502_21 (void)
562 /* Opcode $21: AND (zp,x) */
569 static void OPC_6502_22 (void)
577 static void OPC_6502_23 (void)
585 static void OPC_6502_24 (void)
586 /* Opcode $24: BIT zp */
593 static void OPC_6502_25 (void)
594 /* Opcode $25: AND zp */
601 static void OPC_6502_26 (void)
602 /* Opcode $26: ROL zp */
609 static void OPC_6502_27 (void)
617 static void OPC_6502_28 (void)
618 /* Opcode $28: PLP */
627 static void OPC_6502_29 (void)
628 /* Opcode $29: AND #imm */
635 static void OPC_6502_2A (void)
636 /* Opcode $2A: ROL a */
643 static void OPC_6502_2B (void)
651 static void OPC_6502_2C (void)
652 /* Opcode $2C: BIT abs */
659 static void OPC_6502_2D (void)
660 /* Opcode $2D: AND abs */
667 static void OPC_6502_2E (void)
668 /* Opcode $2E: ROL abs */
675 static void OPC_6502_2F (void)
683 static void OPC_6502_30 (void)
684 /* Opcode $30: BMI */
686 BRANCH (SF_IS_SET ());
691 static void OPC_6502_31 (void)
692 /* Opcode $31: AND (zp),y */
699 static void OPC_6502_32 (void)
707 static void OPC_6502_33 (void)
715 static void OPC_6502_34 (void)
723 static void OPC_6502_35 (void)
724 /* Opcode $35: AND zp,x */
731 static void OPC_6502_36 (void)
732 /* Opcode $36: ROL zp,x */
739 static void OPC_6502_37 (void)
747 static void OPC_6502_38 (void)
748 /* Opcode $38: SEC */
757 static void OPC_6502_39 (void)
758 /* Opcode $39: AND abs,y */
765 static void OPC_6502_3A (void)
773 static void OPC_6502_3B (void)
781 static void OPC_6502_3C (void)
789 static void OPC_6502_3D (void)
790 /* Opcode $3D: AND abs,x */
797 static void OPC_6502_3E (void)
798 /* Opcode $3E: ROL abs,x */
805 static void OPC_6502_3F (void)
813 static void OPC_6502_40 (void)
814 /* Opcode $40: RTI */
818 PC = POP (); /* PCL */
819 PC |= (POP () << 8); /* PCH */
824 static void OPC_6502_41 (void)
825 /* Opcode $41: EOR (zp,x) */
832 static void OPC_6502_42 (void)
840 static void OPC_6502_43 (void)
848 static void OPC_6502_44 (void)
856 static void OPC_6502_45 (void)
857 /* Opcode $45: EOR zp */
864 static void OPC_6502_46 (void)
865 /* Opcode $46: LSR zp */
872 static void OPC_6502_47 (void)
880 static void OPC_6502_48 (void)
881 /* Opcode $48: PHA */
890 static void OPC_6502_49 (void)
891 /* Opcode $49: EOR #imm */
898 static void OPC_6502_4A (void)
899 /* Opcode $4A: LSR a */
906 static void OPC_6502_4B (void)
914 static void OPC_6502_4C (void)
915 /* Opcode $4C: JMP abs */
918 PC = ReadMemW (PC+1);
923 static void OPC_6502_4D (void)
924 /* Opcode $4D: EOR abs */
931 static void OPC_6502_4E (void)
932 /* Opcode $4E: LSR abs */
939 static void OPC_6502_4F (void)
947 static void OPC_6502_50 (void)
948 /* Opcode $50: BVC */
950 BRANCH (!OF_IS_SET());
955 static void OPC_6502_51 (void)
956 /* Opcode $51: EOR (zp),y */
963 static void OPC_6502_52 (void)
971 static void OPC_6502_53 (void)
979 static void OPC_6502_54 (void)
987 static void OPC_6502_55 (void)
988 /* Opcode $55: EOR zp,x */
995 static void OPC_6502_56 (void)
996 /* Opcode $56: LSR zp,x */
1003 static void OPC_6502_57 (void)
1011 static void OPC_6502_58 (void)
1012 /* Opcode $58: CLI */
1021 static void OPC_6502_59 (void)
1022 /* Opcode $59: EOR abs,y */
1029 static void OPC_6502_5A (void)
1037 static void OPC_6502_5B (void)
1045 static void OPC_6502_5C (void)
1053 static void OPC_6502_5D (void)
1054 /* Opcode $5D: EOR abs,x */
1061 static void OPC_6502_5E (void)
1062 /* Opcode $5E: LSR abs,x */
1069 static void OPC_6502_5F (void)
1077 static void OPC_6502_60 (void)
1078 /* Opcode $60: RTS */
1081 PC = POP (); /* PCL */
1082 PC |= (POP () << 8); /* PCH */
1088 static void OPC_6502_61 (void)
1089 /* Opcode $61: ADC (zp,x) */
1096 static void OPC_6502_62 (void)
1104 static void OPC_6502_63 (void)
1112 static void OPC_6502_64 (void)
1120 static void OPC_6502_65 (void)
1121 /* Opcode $65: ADC zp */
1128 static void OPC_6502_66 (void)
1129 /* Opcode $66: ROR zp */
1136 static void OPC_6502_67 (void)
1144 static void OPC_6502_68 (void)
1145 /* Opcode $68: PLA */
1156 static void OPC_6502_69 (void)
1157 /* Opcode $69: ADC #imm */
1164 static void OPC_6502_6A (void)
1165 /* Opcode $6A: ROR a */
1172 static void OPC_6502_6B (void)
1180 static void OPC_6502_6C (void)
1181 /* Opcode $6C: JMP (ind) */
1185 Addr = ReadMemW (PC+1);
1186 if (CPU == CPU_6502) {
1187 /* Emulate the 6502 bug */
1188 PC = ReadMem (Addr);
1189 Addr = (Addr & 0xFF00) | ((Addr + 1) & 0xFF);
1190 PC |= (ReadMem (Addr) << 8);
1192 /* 65C02 and above have this bug fixed */
1193 PC = ReadMemW (Addr);
1200 static void OPC_6502_6D (void)
1201 /* Opcode $6D: ADC abs */
1208 static void OPC_6502_6E (void)
1209 /* Opcode $6E: ROR abs */
1216 static void OPC_6502_6F (void)
1224 static void OPC_6502_70 (void)
1225 /* Opcode $70: BVS */
1227 BRANCH (OF_IS_SET ());
1232 static void OPC_6502_71 (void)
1233 /* Opcode $71: ADC (zp),y */
1240 static void OPC_6502_72 (void)
1248 static void OPC_6502_73 (void)
1256 static void OPC_6502_74 (void)
1264 static void OPC_6502_75 (void)
1265 /* Opcode $75: ADC zp,x */
1272 static void OPC_6502_76 (void)
1273 /* Opcode $76: ROR zp,x */
1280 static void OPC_6502_77 (void)
1288 static void OPC_6502_78 (void)
1289 /* Opcode $78: SEI */
1298 static void OPC_6502_79 (void)
1299 /* Opcode $79: ADC abs,y */
1306 static void OPC_6502_7A (void)
1314 static void OPC_6502_7B (void)
1322 static void OPC_6502_7C (void)
1330 static void OPC_6502_7D (void)
1331 /* Opcode $7D: ADC abs,x */
1338 static void OPC_6502_7E (void)
1339 /* Opcode $7E: ROR abs,x */
1346 static void OPC_6502_7F (void)
1354 static void OPC_6502_80 (void)
1362 static void OPC_6502_81 (void)
1363 /* Opcode $81: STA (zp,x) */
1370 static void OPC_6502_82 (void)
1378 static void OPC_6502_83 (void)
1386 static void OPC_6502_84 (void)
1387 /* Opcode $84: STY zp */
1389 unsigned char ZPAddr;
1391 ZPAddr = ReadMem (PC+1);
1392 WriteMem (ZPAddr, YR);
1398 static void OPC_6502_85 (void)
1399 /* Opcode $85: STA zp */
1401 unsigned char ZPAddr;
1403 ZPAddr = ReadMem (PC+1);
1404 WriteMem (ZPAddr, AC);
1410 static void OPC_6502_86 (void)
1411 /* Opcode $86: STX zp */
1413 unsigned char ZPAddr;
1415 ZPAddr = ReadMem (PC+1);
1416 WriteMem (ZPAddr, XR);
1422 static void OPC_6502_87 (void)
1430 static void OPC_6502_88 (void)
1431 /* Opcode $88: DEY */
1442 static void OPC_6502_89 (void)
1450 static void OPC_6502_8A (void)
1451 /* Opcode $8A: TXA */
1462 static void OPC_6502_8B (void)
1470 static void OPC_6502_8C (void)
1471 /* Opcode $8C: STY abs */
1475 Addr = ReadMemW (PC+1);
1476 WriteMem (Addr, YR);
1482 static void OPC_6502_8D (void)
1483 /* Opcode $8D: STA abs */
1487 Addr = ReadMemW (PC+1);
1488 WriteMem (Addr, AC);
1494 static void OPC_6502_8E (void)
1495 /* Opcode $8E: STX abs */
1499 Addr = ReadMemW (PC+1);
1500 WriteMem (Addr, XR);
1506 static void OPC_6502_8F (void)
1514 static void OPC_6502_90 (void)
1515 /* Opcode $90: BCC */
1517 BRANCH (!CF_IS_SET ());
1522 static void OPC_6502_91 (void)
1523 /* Opcode $91: sta (zp),y */
1525 unsigned char ZPAddr;
1528 ZPAddr = ReadMem (PC+1);
1529 Addr = ReadZeroPageW (ZPAddr) + YR;
1530 WriteMem (Addr, AC);
1536 static void OPC_6502_92 (void)
1544 static void OPC_6502_93 (void)
1552 static void OPC_6502_94 (void)
1553 /* Opcode $94: STY zp,x */
1555 unsigned char ZPAddr;
1557 ZPAddr = ReadMem (PC+1) + XR;
1558 WriteMem (ZPAddr, YR);
1564 static void OPC_6502_95 (void)
1565 /* Opcode $95: STA zp,x */
1567 unsigned char ZPAddr;
1569 ZPAddr = ReadMem (PC+1) + XR;
1570 WriteMem (ZPAddr, AC);
1576 static void OPC_6502_96 (void)
1577 /* Opcode $96: stx zp,y */
1579 unsigned char ZPAddr;
1581 ZPAddr = ReadMem (PC+1) + YR;
1582 WriteMem (ZPAddr, XR);
1588 static void OPC_6502_97 (void)
1596 static void OPC_6502_98 (void)
1597 /* Opcode $98: TYA */
1608 static void OPC_6502_99 (void)
1609 /* Opcode $99: STA abs,y */
1613 Addr = ReadMemW (PC+1) + YR;
1614 WriteMem (Addr, AC);
1620 static void OPC_6502_9A (void)
1621 /* Opcode $9A: TXS */
1630 static void OPC_6502_9B (void)
1638 static void OPC_6502_9C (void)
1646 static void OPC_6502_9D (void)
1647 /* Opcode $9D: STA abs,x */
1651 Addr = ReadMemW (PC+1) + XR;
1652 WriteMem (Addr, AC);
1658 static void OPC_6502_9E (void)
1666 static void OPC_6502_9F (void)
1674 static void OPC_6502_A0 (void)
1675 /* Opcode $A0: LDY #imm */
1678 YR = ReadMem (PC+1);
1686 static void OPC_6502_A1 (void)
1687 /* Opcode $A1: LDA (zp,x) */
1689 unsigned char ZPAddr;
1692 ZPAddr = ReadMem (PC+1) + XR;
1693 Addr = ReadZeroPageW (ZPAddr);
1694 AC = ReadMem (Addr);
1702 static void OPC_6502_A2 (void)
1703 /* Opcode $A2: LDX #imm */
1706 XR = ReadMem (PC+1);
1714 static void OPC_6502_A3 (void)
1722 static void OPC_6502_A4 (void)
1723 /* Opcode $A4: LDY zp */
1725 unsigned char ZPAddr;
1727 ZPAddr = ReadMem (PC+1);
1728 YR = ReadMem (ZPAddr);
1736 static void OPC_6502_A5 (void)
1737 /* Opcode $A5: LDA zp */
1739 unsigned char ZPAddr;
1741 ZPAddr = ReadMem (PC+1);
1742 AC = ReadMem (ZPAddr);
1750 static void OPC_6502_A6 (void)
1751 /* Opcode $A6: LDX zp */
1753 unsigned char ZPAddr;
1755 ZPAddr = ReadMem (PC+1);
1756 XR = ReadMem (ZPAddr);
1764 static void OPC_6502_A7 (void)
1772 static void OPC_6502_A8 (void)
1773 /* Opcode $A8: TAY */
1784 static void OPC_6502_A9 (void)
1785 /* Opcode $A9: LDA #imm */
1788 AC = ReadMem (PC+1);
1796 static void OPC_6502_AA (void)
1797 /* Opcode $AA: TAX */
1808 static void OPC_6502_AB (void)
1816 static void OPC_6502_AC (void)
1817 /* Opcode $AC: LDY abs */
1821 Addr = ReadMemW (PC+1);
1822 YR = ReadMem (Addr);
1830 static void OPC_6502_AD (void)
1831 /* Opcode $AD: LDA abs */
1835 Addr = ReadMemW (PC+1);
1836 AC = ReadMem (Addr);
1844 static void OPC_6502_AE (void)
1845 /* Opcode $AE: LDX abs */
1849 Addr = ReadMemW (PC+1);
1850 XR = ReadMem (Addr);
1858 static void OPC_6502_AF (void)
1866 static void OPC_6502_B0 (void)
1867 /* Opcode $B0: BCS */
1869 BRANCH (CF_IS_SET ());
1874 static void OPC_6502_B1 (void)
1875 /* Opcode $B1: LDA (zp),y */
1877 unsigned char ZPAddr;
1880 ZPAddr = ReadMem (PC+1);
1881 Addr = ReadZeroPageW (ZPAddr);
1882 if (PAGE_CROSS (Addr, YR)) {
1885 AC = ReadMem (Addr + YR);
1893 static void OPC_6502_B2 (void)
1901 static void OPC_6502_B3 (void)
1909 static void OPC_6502_B4 (void)
1910 /* Opcode $B4: LDY zp,x */
1912 unsigned char ZPAddr;
1914 ZPAddr = ReadMem (PC+1) + XR;
1915 YR = ReadMem (ZPAddr);
1923 static void OPC_6502_B5 (void)
1924 /* Opcode $B5: LDA zp,x */
1926 unsigned char ZPAddr;
1928 ZPAddr = ReadMem (PC+1) + XR;
1929 AC = ReadMem (ZPAddr);
1937 static void OPC_6502_B6 (void)
1938 /* Opcode $B6: LDX zp,y */
1940 unsigned char ZPAddr;
1942 ZPAddr = ReadMem (PC+1) + YR;
1943 XR = ReadMem (ZPAddr);
1951 static void OPC_6502_B7 (void)
1959 static void OPC_6502_B8 (void)
1960 /* Opcode $B8: CLV */
1969 static void OPC_6502_B9 (void)
1970 /* Opcode $B9: LDA abs,y */
1974 Addr = ReadMemW (PC+1);
1975 if (PAGE_CROSS (Addr, YR)) {
1978 AC = ReadMem (Addr + YR);
1986 static void OPC_6502_BA (void)
1987 /* Opcode $BA: TSX */
1998 static void OPC_6502_BB (void)
2006 static void OPC_6502_BC (void)
2007 /* Opcode $BC: LDY abs,x */
2011 Addr = ReadMemW (PC+1);
2012 if (PAGE_CROSS (Addr, XR)) {
2015 YR = ReadMem (Addr + XR);
2023 static void OPC_6502_BD (void)
2024 /* Opcode $BD: LDA abs,x */
2028 Addr = ReadMemW (PC+1);
2029 if (PAGE_CROSS (Addr, XR)) {
2032 AC = ReadMem (Addr + XR);
2040 static void OPC_6502_BE (void)
2041 /* Opcode $BE: LDX abs,y */
2045 Addr = ReadMemW (PC+1);
2046 if (PAGE_CROSS (Addr, YR)) {
2049 XR = ReadMem (Addr + YR);
2057 static void OPC_6502_BF (void)
2065 static void OPC_6502_C0 (void)
2066 /* Opcode $C0: CPY #imm */
2069 CMP (YR, ReadMem (PC+1));
2075 static void OPC_6502_C1 (void)
2076 /* Opcode $C1: CMP (zp,x) */
2078 unsigned char ZPAddr;
2081 ZPAddr = ReadMem (PC+1) + XR;
2082 Addr = ReadZeroPageW (ZPAddr);
2083 CMP (AC, ReadMem (Addr));
2089 static void OPC_6502_C2 (void)
2097 static void OPC_6502_C3 (void)
2105 static void OPC_6502_C4 (void)
2106 /* Opcode $C4: CPY zp */
2108 unsigned char ZPAddr;
2110 ZPAddr = ReadMem (PC+1);
2111 CMP (YR, ReadMem (ZPAddr));
2117 static void OPC_6502_C5 (void)
2118 /* Opcode $C5: CMP zp */
2120 unsigned char ZPAddr;
2122 ZPAddr = ReadMem (PC+1);
2123 CMP (AC, ReadMem (ZPAddr));
2129 static void OPC_6502_C6 (void)
2130 /* Opcode $C6: DEC zp */
2132 unsigned char ZPAddr;
2135 ZPAddr = ReadMem (PC+1);
2136 Val = ReadMem (ZPAddr) - 1;
2137 WriteMem (ZPAddr, Val);
2145 static void OPC_6502_C7 (void)
2153 static void OPC_6502_C8 (void)
2154 /* Opcode $C8: INY */
2165 static void OPC_6502_C9 (void)
2166 /* Opcode $C9: CMP #imm */
2169 CMP (AC, ReadMem (PC+1));
2175 static void OPC_6502_CA (void)
2176 /* Opcode $CA: DEX */
2187 static void OPC_6502_CB (void)
2195 static void OPC_6502_CC (void)
2196 /* Opcode $CC: CPY abs */
2200 Addr = ReadMemW (PC+1);
2201 CMP (YR, ReadMem (Addr));
2207 static void OPC_6502_CD (void)
2208 /* Opcode $CD: CMP abs */
2212 Addr = ReadMemW (PC+1);
2213 CMP (AC, ReadMem (Addr));
2219 static void OPC_6502_CE (void)
2220 /* Opcode $CE: DEC abs */
2225 Addr = ReadMemW (PC+1);
2226 Val = ReadMem (Addr) - 1;
2227 WriteMem (Addr, Val);
2235 static void OPC_6502_CF (void)
2243 static void OPC_6502_D0 (void)
2244 /* Opcode $D0: BNE */
2246 BRANCH (!ZF_IS_SET ());
2251 static void OPC_6502_D1 (void)
2252 /* Opcode $D1: CMP (zp),y */
2257 ZPAddr = ReadMem (PC+1);
2258 Addr = ReadMemW (ZPAddr);
2259 if (PAGE_CROSS (Addr, YR)) {
2262 CMP (AC, ReadMem (Addr + YR));
2268 static void OPC_6502_D2 (void)
2276 static void OPC_6502_D3 (void)
2284 static void OPC_6502_D4 (void)
2292 static void OPC_6502_D5 (void)
2293 /* Opcode $D5: CMP zp,x */
2295 unsigned char ZPAddr;
2297 ZPAddr = ReadMem (PC+1) + XR;
2298 CMP (AC, ReadMem (ZPAddr));
2304 static void OPC_6502_D6 (void)
2305 /* Opcode $D6: DEC zp,x */
2307 unsigned char ZPAddr;
2310 ZPAddr = ReadMem (PC+1) + XR;
2311 Val = ReadMem (ZPAddr) - 1;
2312 WriteMem (ZPAddr, Val);
2320 static void OPC_6502_D7 (void)
2328 static void OPC_6502_D8 (void)
2329 /* Opcode $D8: CLD */
2336 static void OPC_6502_D9 (void)
2337 /* Opcode $D9: CMP abs,y */
2341 Addr = ReadMemW (PC+1);
2342 if (PAGE_CROSS (Addr, YR)) {
2345 CMP (AC, ReadMem (Addr + YR));
2351 static void OPC_6502_DA (void)
2359 static void OPC_6502_DB (void)
2367 static void OPC_6502_DC (void)
2375 static void OPC_6502_DD (void)
2376 /* Opcode $DD: CMP abs,x */
2380 Addr = ReadMemW (PC+1);
2381 if (PAGE_CROSS (Addr, XR)) {
2384 CMP (AC, ReadMem (Addr + XR));
2390 static void OPC_6502_DE (void)
2391 /* Opcode $DE: DEC abs,x */
2396 Addr = ReadMemW (PC+1) + XR;
2397 Val = ReadMem (Addr) - 1;
2398 WriteMem (Addr, Val);
2406 static void OPC_6502_DF (void)
2414 static void OPC_6502_E0 (void)
2415 /* Opcode $E0: CPX #imm */
2418 CMP (XR, ReadMem (PC+1));
2424 static void OPC_6502_E1 (void)
2431 static void OPC_6502_E2 (void)
2439 static void OPC_6502_E3 (void)
2447 static void OPC_6502_E4 (void)
2448 /* Opcode $E4: CPX zp */
2450 unsigned char ZPAddr;
2452 ZPAddr = ReadMem (PC+1);
2453 CMP (XR, ReadMem (ZPAddr));
2459 static void OPC_6502_E5 (void)
2466 static void OPC_6502_E6 (void)
2467 /* Opcode $E6: INC zp */
2469 unsigned char ZPAddr;
2472 ZPAddr = ReadMem (PC+1);
2473 Val = ReadMem (ZPAddr) + 1;
2474 WriteMem (ZPAddr, Val);
2482 static void OPC_6502_E7 (void)
2490 static void OPC_6502_E8 (void)
2491 /* Opcode $E8: INX */
2502 static void OPC_6502_E9 (void)
2509 static void OPC_6502_EA (void)
2510 /* Opcode $EA: NOP */
2512 /* This one is easy... */
2519 static void OPC_6502_EB (void)
2527 static void OPC_6502_EC (void)
2528 /* Opcode $EC: CPX abs */
2532 Addr = ReadMemW (PC+1);
2533 CMP (XR, ReadMem (Addr));
2539 static void OPC_6502_ED (void)
2546 static void OPC_6502_EE (void)
2547 /* Opcode $EE: INC abs */
2552 Addr = ReadMemW (PC+1);
2553 Val = ReadMem (Addr) + 1;
2554 WriteMem (Addr, Val);
2562 static void OPC_6502_EF (void)
2570 static void OPC_6502_F0 (void)
2571 /* Opcode $F0: BEQ */
2573 BRANCH (ZF_IS_SET ());
2578 static void OPC_6502_F1 (void)
2585 static void OPC_6502_F2 (void)
2593 static void OPC_6502_F3 (void)
2601 static void OPC_6502_F4 (void)
2609 static void OPC_6502_F5 (void)
2616 static void OPC_6502_F6 (void)
2617 /* Opcode $F6: INC zp,x */
2619 unsigned char ZPAddr;
2622 ZPAddr = ReadMem (PC+1) + XR;
2623 Val = ReadMem (ZPAddr) + 1;
2624 WriteMem (ZPAddr, Val);
2632 static void OPC_6502_F7 (void)
2640 static void OPC_6502_F8 (void)
2641 /* Opcode $F8: SED */
2648 static void OPC_6502_F9 (void)
2655 static void OPC_6502_FA (void)
2663 static void OPC_6502_FB (void)
2671 static void OPC_6502_FC (void)
2679 static void OPC_6502_FD (void)
2686 static void OPC_6502_FE (void)
2687 /* Opcode $FE: INC abs,x */
2692 Addr = ReadMemW (PC+1) + XR;
2693 Val = ReadMem (Addr) + 1;
2694 WriteMem (Addr, Val);
2702 static void OPC_6502_FF (void)
2710 /*****************************************************************************/
2712 /*****************************************************************************/
2716 /* Opcode handler table */
2717 typedef void (*OPCFunc) (void);
2718 static OPCFunc OPCTable[256] = {
2979 /*****************************************************************************/
2981 /*****************************************************************************/
2988 while (!CPUHalted) {
2990 /* Get the next opcode */
2991 unsigned char B = 0x00;