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 /*****************************************************************************/
91 /* Return the flags as a boolean value */
92 #define GET_CF() ((SR & CF) != 0)
93 #define GET_ZF() ((SR & ZF) != 0)
94 #define GET_IF() ((SR & IF) != 0)
95 #define GET_DF() ((SR & DF) != 0)
96 #define GET_BF() ((SR & BF) != 0)
97 #define GET_OF() ((SR & OF) != 0)
98 #define GET_SF() ((SR & SF) != 0)
100 /* Set the flags. The parameter is a boolean flag that says if the flag should be
103 #define SET_CF(f) do { if (f) { SR |= CF; } else { SR &= ~CF; } } while (0)
104 #define SET_ZF(f) do { if (f) { SR |= ZF; } else { SR &= ~ZF; } } while (0)
105 #define SET_IF(f) do { if (f) { SR |= IF; } else { SR &= ~IF; } } while (0)
106 #define SET_DF(f) do { if (f) { SR |= DF; } else { SR &= ~DF; } } while (0)
107 #define SET_BF(f) do { if (f) { SR |= BF; } else { SR &= ~BF; } } while (0)
108 #define SET_OF(f) do { if (f) { SR |= OF; } else { SR &= ~OF; } } while (0)
109 #define SET_SF(f) do { if (f) { SR |= SF; } else { SR &= ~SF; } } while (0)
111 /* Special test and set macros. The meaning of the parameter depends on the
112 * actual flag that should be set or reset.
114 #define TEST_ZF(v) SET_ZF (((v) & 0xFF) == 0)
115 #define TEST_SF(v) SET_SF (((v) & 0x80) != 0)
116 #define TEST_CF(v) SET_CF (((v) & 0xFF00) != 0)
118 /* Program counter halves */
119 #define PCL (PC & 0xFF)
120 #define PCH ((PC >> 8) & 0xFF)
122 /* Stack operations */
123 #define PUSH(Val) WriteMem (StackPage + SP--, Val)
124 #define POP() ReadMem (StackPage + ++SP)
126 /* Test for page cross */
127 #define PAGE_CROSS(addr,offs) ((((addr) & 0xFF) + offs) >= 0x100)
130 #define AC_OP_IMM(op) \
132 AC = AC op ReadMem (PC+1); \
138 #define AC_OP_ZP(op) \
140 AC = AC op ReadMem (ReadMem (PC+1)); \
146 #define AC_OP_ZPX(op) \
147 unsigned char ZPAddr; \
149 ZPAddr = ReadMem (PC+1) + XR; \
150 AC = AC op ReadMem (ZPAddr); \
156 #define AC_OP_ZPY(op) \
157 unsigned char ZPAddr; \
159 ZPAddr = ReadMem (PC+1) + YR; \
160 AC = AC op ReadMem (ZPAddr); \
166 #define AC_OP_ABS(op) \
169 Addr = ReadMemW (PC+1); \
170 AC = AC op ReadMem (Addr); \
176 #define AC_OP_ABSX(op) \
179 Addr = ReadMemW (PC+1); \
180 if (PAGE_CROSS (Addr, XR)) { \
183 AC = AC | ReadMem (Addr + XR); \
189 #define AC_OP_ABSY(op) \
192 Addr = ReadMemW (PC+1); \
193 if (PAGE_CROSS (Addr, YR)) { \
196 AC = AC | ReadMem (Addr + YR); \
202 #define AC_OP_ZPXIND(op) \
203 unsigned char ZPAddr; \
206 ZPAddr = ReadMem (PC+1) + XR; \
207 Addr = ReadZeroPageW (ZPAddr); \
208 AC = AC op ReadMem (Addr); \
214 #define AC_OP_ZPINDY(op) \
215 unsigned char ZPAddr; \
218 ZPAddr = ReadMem (PC+1); \
219 Addr = ReadZeroPageW (ZPAddr) + YR; \
220 AC = AC op ReadMem (Addr); \
226 #define BRANCH(cond) \
230 unsigned char OldPCH; \
232 Offs = (signed char) ReadMem (PC+1); \
235 if (PCH != OldPCH) { \
245 unsigned Result = v1 - v2; \
246 TEST_ZF (Result & 0xFF); \
248 SET_CF (Result <= 0xFF); \
253 /*****************************************************************************/
254 /* Helper functions */
255 /*****************************************************************************/
259 static void Illegal (void)
261 fprintf (stderr, "Illegal: $%02X\n", ReadMem (PC));
267 static void NotImplemented (void)
269 fprintf (stderr, "Not implemented: $%02X\n", ReadMem (PC));
275 /*****************************************************************************/
277 /*****************************************************************************/
281 static void OPC_6502_00 (void)
282 /* Opcode $00: BRK */
291 PC = ReadMemW (0xFFFE);
296 static void OPC_6502_01 (void)
297 /* Opcode $01: ORA (ind,x) */
304 static void OPC_6502_02 (void)
312 static void OPC_6502_03 (void)
320 static void OPC_6502_04 (void)
328 static void OPC_6502_05 (void)
329 /* Opcode $05: ORA zp */
336 static void OPC_6502_06 (void)
337 /* Opcode $06: ASL zp */
339 unsigned char ZPAddr;
342 ZPAddr = ReadMem (PC+1);
343 Val = ReadMem (ZPAddr) << 1;
344 WriteMem (ZPAddr, (unsigned char) Val);
345 TEST_ZF (Val & 0xFF);
347 SET_CF (Val & 0x100);
353 static void OPC_6502_07 (void)
361 static void OPC_6502_08 (void)
362 /* Opcode $08: PHP */
371 static void OPC_6502_09 (void)
372 /* Opcode $09: ORA #imm */
379 static void OPC_6502_0A (void)
380 /* Opcode $0A: ASL a */
385 AC = (unsigned char) Val;
386 TEST_ZF (Val & 0xFF);
388 SET_CF (Val & 0x100);
394 static void OPC_6502_0B (void)
402 static void OPC_6502_0C (void)
410 static void OPC_6502_0D (void)
411 /* Opcode $0D: ORA abs */
418 static void OPC_6502_0E (void)
419 /* Opcode $0E: ALS abs */
424 Addr = ReadMemW (PC+1);
425 Val = ReadMem (Addr) << 1;
426 WriteMem (Addr, (unsigned char) Val);
427 TEST_ZF (Val & 0xFF);
429 SET_CF (Val & 0x100);
435 static void OPC_6502_0F (void)
443 static void OPC_6502_10 (void)
444 /* Opcode $10: BPL */
451 static void OPC_6502_11 (void)
452 /* Opcode $11: ORA (zp),y */
459 static void OPC_6502_12 (void)
467 static void OPC_6502_13 (void)
475 static void OPC_6502_14 (void)
483 static void OPC_6502_15 (void)
484 /* Opcode $15: ORA zp,x */
491 static void OPC_6502_16 (void)
492 /* Opcode $16: ASL zp,x */
494 unsigned char ZPAddr;
497 ZPAddr = ReadMem (PC+1) + XR;
498 Val = ReadMem (ZPAddr) << 1;
499 WriteMem (ZPAddr, (unsigned char) Val);
500 TEST_ZF (Val & 0xFF);
502 SET_CF (Val & 0x100);
508 static void OPC_6502_17 (void)
516 static void OPC_6502_18 (void)
517 /* Opcode $18: CLC */
526 static void OPC_6502_19 (void)
527 /* Opcode $19: ORA abs,y */
534 static void OPC_6502_1A (void)
542 static void OPC_6502_1B (void)
550 static void OPC_6502_1C (void)
558 static void OPC_6502_1D (void)
559 /* Opcode $1D: ORA abs,x */
566 static void OPC_6502_1E (void)
567 /* Opcode $1E: ASL abs,x */
572 Addr = ReadMemW (PC+1) + XR;
573 Val = ReadMem (Addr) << 1;
574 WriteMem (Addr, (unsigned char) Val);
575 TEST_ZF (Val & 0xFF);
577 SET_CF (Val & 0x100);
583 static void OPC_6502_1F (void)
591 static void OPC_6502_20 (void)
592 /* Opcode $20: JSR */
596 Addr = ReadMemW (PC+1);
605 static void OPC_6502_21 (void)
606 /* Opcode $21: AND (zp,x) */
613 static void OPC_6502_22 (void)
621 static void OPC_6502_23 (void)
629 static void OPC_6502_24 (void)
630 /* Opcode $24: BIT zp */
632 unsigned char ZPAddr;
635 ZPAddr = ReadMem (PC+1);
636 Val = ReadMem (ZPAddr);
639 SET_ZF ((Val & AC) == 0);
645 static void OPC_6502_25 (void)
646 /* Opcode $25: AND zp */
653 static void OPC_6502_26 (void)
654 /* Opcode $26: ROL zp */
656 unsigned char ZPAddr;
659 ZPAddr = ReadMem (PC+1);
660 Val = ReadMem (ZPAddr) << 1;
664 AC = (unsigned char) Val;
673 static void OPC_6502_27 (void)
681 static void OPC_6502_28 (void)
682 /* Opcode $28: PLP */
691 static void OPC_6502_29 (void)
692 /* Opcode $29: AND #imm */
699 static void OPC_6502_2A (void)
700 /* Opcode $2A: ROL a */
708 AC = (unsigned char) Val;
717 static void OPC_6502_2B (void)
725 static void OPC_6502_2C (void)
726 /* Opcode $2C: BIT abs */
731 Addr = ReadMem (PC+1);
732 Val = ReadMem (Addr);
735 SET_ZF ((Val & AC) == 0);
741 static void OPC_6502_2D (void)
742 /* Opcode $2D: AND abs */
749 static void OPC_6502_2E (void)
750 /* Opcode $2E: ROL abs */
755 Addr = ReadMemW (PC+1);
756 Val = ReadMem (Addr) << 1;
760 AC = (unsigned char) Val;
769 static void OPC_6502_2F (void)
777 static void OPC_6502_30 (void)
778 /* Opcode $30: BMI */
785 static void OPC_6502_31 (void)
786 /* Opcode $31: AND (zp),y */
793 static void OPC_6502_32 (void)
801 static void OPC_6502_33 (void)
809 static void OPC_6502_34 (void)
817 static void OPC_6502_35 (void)
818 /* Opcode $35: AND zp,x */
825 static void OPC_6502_36 (void)
826 /* Opcode $36: ROL zp,x */
828 unsigned char ZPAddr;
831 ZPAddr = ReadMem (PC+1) + XR;
832 Val = ReadMem (ZPAddr) << 1;
836 AC = (unsigned char) Val;
845 static void OPC_6502_37 (void)
853 static void OPC_6502_38 (void)
854 /* Opcode $38: SEC */
863 static void OPC_6502_39 (void)
864 /* Opcode $39: AND abs,y */
871 static void OPC_6502_3A (void)
879 static void OPC_6502_3B (void)
887 static void OPC_6502_3C (void)
895 static void OPC_6502_3D (void)
896 /* Opcode $3D: AND abs,x */
903 static void OPC_6502_3E (void)
904 /* Opcode $3E: ROL abs,x */
909 Addr = ReadMemW (PC+1) + XR;
910 Val = ReadMem (Addr) << 1;
914 AC = (unsigned char) Val;
923 static void OPC_6502_3F (void)
931 static void OPC_6502_40 (void)
932 /* Opcode $40: RTI */
936 PC = POP (); /* PCL */
937 PC |= (POP () << 8); /* PCH */
942 static void OPC_6502_41 (void)
943 /* Opcode $41: EOR (zp,x) */
950 static void OPC_6502_42 (void)
958 static void OPC_6502_43 (void)
966 static void OPC_6502_44 (void)
974 static void OPC_6502_45 (void)
975 /* Opcode $45: EOR zp */
982 static void OPC_6502_46 (void)
983 /* Opcode $46: LSR zp */
985 unsigned char ZPAddr;
988 ZPAddr = ReadMem (PC+1);
989 Val = ReadMem (ZPAddr);
992 WriteMem (ZPAddr, Val);
1000 static void OPC_6502_47 (void)
1008 static void OPC_6502_48 (void)
1009 /* Opcode $48: PHA */
1018 static void OPC_6502_49 (void)
1019 /* Opcode $49: EOR #imm */
1026 static void OPC_6502_4A (void)
1027 /* Opcode $4A: LSR a */
1039 static void OPC_6502_4B (void)
1047 static void OPC_6502_4C (void)
1048 /* Opcode $4C: JMP abs */
1051 PC = ReadMemW (PC+1);
1056 static void OPC_6502_4D (void)
1057 /* Opcode $4D: EOR abs */
1064 static void OPC_6502_4E (void)
1065 /* Opcode $4E: LSR abs */
1070 Addr = ReadMemW (PC+1);
1071 Val = ReadMem (Addr);
1072 SET_CF (Val & 0x01);
1074 WriteMem (Addr, Val);
1082 static void OPC_6502_4F (void)
1090 static void OPC_6502_50 (void)
1091 /* Opcode $50: BVC */
1093 BRANCH (!GET_OF ());
1098 static void OPC_6502_51 (void)
1099 /* Opcode $51: EOR (zp),y */
1106 static void OPC_6502_52 (void)
1114 static void OPC_6502_53 (void)
1122 static void OPC_6502_54 (void)
1130 static void OPC_6502_55 (void)
1131 /* Opcode $55: EOR zp,x */
1138 static void OPC_6502_56 (void)
1139 /* Opcode $56: LSR zp,x */
1141 unsigned char ZPAddr;
1144 ZPAddr = ReadMem (PC+1) + XR;
1145 Val = ReadMem (ZPAddr);
1146 SET_CF (Val & 0x01);
1148 WriteMem (ZPAddr, Val);
1156 static void OPC_6502_57 (void)
1164 static void OPC_6502_58 (void)
1165 /* Opcode $58: CLI */
1174 static void OPC_6502_59 (void)
1175 /* Opcode $59: EOR abs,y */
1182 static void OPC_6502_5A (void)
1190 static void OPC_6502_5B (void)
1198 static void OPC_6502_5C (void)
1206 static void OPC_6502_5D (void)
1207 /* Opcode $5D: EOR abs,x */
1214 static void OPC_6502_5E (void)
1215 /* Opcode $5E: LSR abs,x */
1220 Addr = ReadMemW (PC+1) + XR;
1221 Val = ReadMem (Addr);
1222 SET_CF (Val & 0x01);
1224 WriteMem (Addr, Val);
1232 static void OPC_6502_5F (void)
1240 static void OPC_6502_60 (void)
1241 /* Opcode $60: RTS */
1244 PC = POP (); /* PCL */
1245 PC |= (POP () << 8); /* PCH */
1251 static void OPC_6502_61 (void)
1252 /* Opcode $61: ADC (zp,x) */
1259 static void OPC_6502_62 (void)
1267 static void OPC_6502_63 (void)
1275 static void OPC_6502_64 (void)
1283 static void OPC_6502_65 (void)
1284 /* Opcode $65: ADC zp */
1291 static void OPC_6502_66 (void)
1292 /* Opcode $66: ROR zp */
1299 static void OPC_6502_67 (void)
1307 static void OPC_6502_68 (void)
1308 /* Opcode $68: PLA */
1319 static void OPC_6502_69 (void)
1320 /* Opcode $69: ADC #imm */
1327 static void OPC_6502_6A (void)
1328 /* Opcode $6A: ROR a */
1335 static void OPC_6502_6B (void)
1343 static void OPC_6502_6C (void)
1344 /* Opcode $6C: JMP (ind) */
1348 Addr = ReadMemW (PC+1);
1349 if (CPU == CPU_6502) {
1350 /* Emulate the 6502 bug */
1351 PC = ReadMem (Addr);
1352 Addr = (Addr & 0xFF00) | ((Addr + 1) & 0xFF);
1353 PC |= (ReadMem (Addr) << 8);
1355 /* 65C02 and above have this bug fixed */
1356 PC = ReadMemW (Addr);
1363 static void OPC_6502_6D (void)
1364 /* Opcode $6D: ADC abs */
1371 static void OPC_6502_6E (void)
1372 /* Opcode $6E: ROR abs */
1379 static void OPC_6502_6F (void)
1387 static void OPC_6502_70 (void)
1388 /* Opcode $70: BVS */
1395 static void OPC_6502_71 (void)
1396 /* Opcode $71: ADC (zp),y */
1403 static void OPC_6502_72 (void)
1411 static void OPC_6502_73 (void)
1419 static void OPC_6502_74 (void)
1427 static void OPC_6502_75 (void)
1428 /* Opcode $75: ADC zp,x */
1435 static void OPC_6502_76 (void)
1436 /* Opcode $76: ROR zp,x */
1443 static void OPC_6502_77 (void)
1451 static void OPC_6502_78 (void)
1452 /* Opcode $78: SEI */
1461 static void OPC_6502_79 (void)
1462 /* Opcode $79: ADC abs,y */
1469 static void OPC_6502_7A (void)
1477 static void OPC_6502_7B (void)
1485 static void OPC_6502_7C (void)
1493 static void OPC_6502_7D (void)
1494 /* Opcode $7D: ADC abs,x */
1501 static void OPC_6502_7E (void)
1502 /* Opcode $7E: ROR abs,x */
1509 static void OPC_6502_7F (void)
1517 static void OPC_6502_80 (void)
1525 static void OPC_6502_81 (void)
1526 /* Opcode $81: STA (zp,x) */
1533 static void OPC_6502_82 (void)
1541 static void OPC_6502_83 (void)
1549 static void OPC_6502_84 (void)
1550 /* Opcode $84: STY zp */
1552 unsigned char ZPAddr;
1554 ZPAddr = ReadMem (PC+1);
1555 WriteMem (ZPAddr, YR);
1561 static void OPC_6502_85 (void)
1562 /* Opcode $85: STA zp */
1564 unsigned char ZPAddr;
1566 ZPAddr = ReadMem (PC+1);
1567 WriteMem (ZPAddr, AC);
1573 static void OPC_6502_86 (void)
1574 /* Opcode $86: STX zp */
1576 unsigned char ZPAddr;
1578 ZPAddr = ReadMem (PC+1);
1579 WriteMem (ZPAddr, XR);
1585 static void OPC_6502_87 (void)
1593 static void OPC_6502_88 (void)
1594 /* Opcode $88: DEY */
1605 static void OPC_6502_89 (void)
1613 static void OPC_6502_8A (void)
1614 /* Opcode $8A: TXA */
1625 static void OPC_6502_8B (void)
1633 static void OPC_6502_8C (void)
1634 /* Opcode $8C: STY abs */
1638 Addr = ReadMemW (PC+1);
1639 WriteMem (Addr, YR);
1645 static void OPC_6502_8D (void)
1646 /* Opcode $8D: STA abs */
1650 Addr = ReadMemW (PC+1);
1651 WriteMem (Addr, AC);
1657 static void OPC_6502_8E (void)
1658 /* Opcode $8E: STX abs */
1662 Addr = ReadMemW (PC+1);
1663 WriteMem (Addr, XR);
1669 static void OPC_6502_8F (void)
1677 static void OPC_6502_90 (void)
1678 /* Opcode $90: BCC */
1680 BRANCH (!GET_CF ());
1685 static void OPC_6502_91 (void)
1686 /* Opcode $91: sta (zp),y */
1688 unsigned char ZPAddr;
1691 ZPAddr = ReadMem (PC+1);
1692 Addr = ReadZeroPageW (ZPAddr) + YR;
1693 WriteMem (Addr, AC);
1699 static void OPC_6502_92 (void)
1707 static void OPC_6502_93 (void)
1715 static void OPC_6502_94 (void)
1716 /* Opcode $94: STY zp,x */
1718 unsigned char ZPAddr;
1720 ZPAddr = ReadMem (PC+1) + XR;
1721 WriteMem (ZPAddr, YR);
1727 static void OPC_6502_95 (void)
1728 /* Opcode $95: STA zp,x */
1730 unsigned char ZPAddr;
1732 ZPAddr = ReadMem (PC+1) + XR;
1733 WriteMem (ZPAddr, AC);
1739 static void OPC_6502_96 (void)
1740 /* Opcode $96: stx zp,y */
1742 unsigned char ZPAddr;
1744 ZPAddr = ReadMem (PC+1) + YR;
1745 WriteMem (ZPAddr, XR);
1751 static void OPC_6502_97 (void)
1759 static void OPC_6502_98 (void)
1760 /* Opcode $98: TYA */
1771 static void OPC_6502_99 (void)
1772 /* Opcode $99: STA abs,y */
1776 Addr = ReadMemW (PC+1) + YR;
1777 WriteMem (Addr, AC);
1783 static void OPC_6502_9A (void)
1784 /* Opcode $9A: TXS */
1793 static void OPC_6502_9B (void)
1801 static void OPC_6502_9C (void)
1809 static void OPC_6502_9D (void)
1810 /* Opcode $9D: STA abs,x */
1814 Addr = ReadMemW (PC+1) + XR;
1815 WriteMem (Addr, AC);
1821 static void OPC_6502_9E (void)
1829 static void OPC_6502_9F (void)
1837 static void OPC_6502_A0 (void)
1838 /* Opcode $A0: LDY #imm */
1841 YR = ReadMem (PC+1);
1849 static void OPC_6502_A1 (void)
1850 /* Opcode $A1: LDA (zp,x) */
1852 unsigned char ZPAddr;
1855 ZPAddr = ReadMem (PC+1) + XR;
1856 Addr = ReadZeroPageW (ZPAddr);
1857 AC = ReadMem (Addr);
1865 static void OPC_6502_A2 (void)
1866 /* Opcode $A2: LDX #imm */
1869 XR = ReadMem (PC+1);
1877 static void OPC_6502_A3 (void)
1885 static void OPC_6502_A4 (void)
1886 /* Opcode $A4: LDY zp */
1888 unsigned char ZPAddr;
1890 ZPAddr = ReadMem (PC+1);
1891 YR = ReadMem (ZPAddr);
1899 static void OPC_6502_A5 (void)
1900 /* Opcode $A5: LDA zp */
1902 unsigned char ZPAddr;
1904 ZPAddr = ReadMem (PC+1);
1905 AC = ReadMem (ZPAddr);
1913 static void OPC_6502_A6 (void)
1914 /* Opcode $A6: LDX zp */
1916 unsigned char ZPAddr;
1918 ZPAddr = ReadMem (PC+1);
1919 XR = ReadMem (ZPAddr);
1927 static void OPC_6502_A7 (void)
1935 static void OPC_6502_A8 (void)
1936 /* Opcode $A8: TAY */
1947 static void OPC_6502_A9 (void)
1948 /* Opcode $A9: LDA #imm */
1951 AC = ReadMem (PC+1);
1959 static void OPC_6502_AA (void)
1960 /* Opcode $AA: TAX */
1971 static void OPC_6502_AB (void)
1979 static void OPC_6502_AC (void)
1980 /* Opcode $AC: LDY abs */
1984 Addr = ReadMemW (PC+1);
1985 YR = ReadMem (Addr);
1993 static void OPC_6502_AD (void)
1994 /* Opcode $AD: LDA abs */
1998 Addr = ReadMemW (PC+1);
1999 AC = ReadMem (Addr);
2007 static void OPC_6502_AE (void)
2008 /* Opcode $AE: LDX abs */
2012 Addr = ReadMemW (PC+1);
2013 XR = ReadMem (Addr);
2021 static void OPC_6502_AF (void)
2029 static void OPC_6502_B0 (void)
2030 /* Opcode $B0: BCS */
2037 static void OPC_6502_B1 (void)
2038 /* Opcode $B1: LDA (zp),y */
2040 unsigned char ZPAddr;
2043 ZPAddr = ReadMem (PC+1);
2044 Addr = ReadZeroPageW (ZPAddr);
2045 if (PAGE_CROSS (Addr, YR)) {
2048 AC = ReadMem (Addr + YR);
2056 static void OPC_6502_B2 (void)
2064 static void OPC_6502_B3 (void)
2072 static void OPC_6502_B4 (void)
2073 /* Opcode $B4: LDY zp,x */
2075 unsigned char ZPAddr;
2077 ZPAddr = ReadMem (PC+1) + XR;
2078 YR = ReadMem (ZPAddr);
2086 static void OPC_6502_B5 (void)
2087 /* Opcode $B5: LDA zp,x */
2089 unsigned char ZPAddr;
2091 ZPAddr = ReadMem (PC+1) + XR;
2092 AC = ReadMem (ZPAddr);
2100 static void OPC_6502_B6 (void)
2101 /* Opcode $B6: LDX zp,y */
2103 unsigned char ZPAddr;
2105 ZPAddr = ReadMem (PC+1) + YR;
2106 XR = ReadMem (ZPAddr);
2114 static void OPC_6502_B7 (void)
2122 static void OPC_6502_B8 (void)
2123 /* Opcode $B8: CLV */
2132 static void OPC_6502_B9 (void)
2133 /* Opcode $B9: LDA abs,y */
2137 Addr = ReadMemW (PC+1);
2138 if (PAGE_CROSS (Addr, YR)) {
2141 AC = ReadMem (Addr + YR);
2149 static void OPC_6502_BA (void)
2150 /* Opcode $BA: TSX */
2161 static void OPC_6502_BB (void)
2169 static void OPC_6502_BC (void)
2170 /* Opcode $BC: LDY abs,x */
2174 Addr = ReadMemW (PC+1);
2175 if (PAGE_CROSS (Addr, XR)) {
2178 YR = ReadMem (Addr + XR);
2186 static void OPC_6502_BD (void)
2187 /* Opcode $BD: LDA abs,x */
2191 Addr = ReadMemW (PC+1);
2192 if (PAGE_CROSS (Addr, XR)) {
2195 AC = ReadMem (Addr + XR);
2203 static void OPC_6502_BE (void)
2204 /* Opcode $BE: LDX abs,y */
2208 Addr = ReadMemW (PC+1);
2209 if (PAGE_CROSS (Addr, YR)) {
2212 XR = ReadMem (Addr + YR);
2220 static void OPC_6502_BF (void)
2228 static void OPC_6502_C0 (void)
2229 /* Opcode $C0: CPY #imm */
2232 CMP (YR, ReadMem (PC+1));
2238 static void OPC_6502_C1 (void)
2239 /* Opcode $C1: CMP (zp,x) */
2241 unsigned char ZPAddr;
2244 ZPAddr = ReadMem (PC+1) + XR;
2245 Addr = ReadZeroPageW (ZPAddr);
2246 CMP (AC, ReadMem (Addr));
2252 static void OPC_6502_C2 (void)
2260 static void OPC_6502_C3 (void)
2268 static void OPC_6502_C4 (void)
2269 /* Opcode $C4: CPY zp */
2271 unsigned char ZPAddr;
2273 ZPAddr = ReadMem (PC+1);
2274 CMP (YR, ReadMem (ZPAddr));
2280 static void OPC_6502_C5 (void)
2281 /* Opcode $C5: CMP zp */
2283 unsigned char ZPAddr;
2285 ZPAddr = ReadMem (PC+1);
2286 CMP (AC, ReadMem (ZPAddr));
2292 static void OPC_6502_C6 (void)
2293 /* Opcode $C6: DEC zp */
2295 unsigned char ZPAddr;
2298 ZPAddr = ReadMem (PC+1);
2299 Val = ReadMem (ZPAddr) - 1;
2300 WriteMem (ZPAddr, Val);
2308 static void OPC_6502_C7 (void)
2316 static void OPC_6502_C8 (void)
2317 /* Opcode $C8: INY */
2328 static void OPC_6502_C9 (void)
2329 /* Opcode $C9: CMP #imm */
2332 CMP (AC, ReadMem (PC+1));
2338 static void OPC_6502_CA (void)
2339 /* Opcode $CA: DEX */
2350 static void OPC_6502_CB (void)
2358 static void OPC_6502_CC (void)
2359 /* Opcode $CC: CPY abs */
2363 Addr = ReadMemW (PC+1);
2364 CMP (YR, ReadMem (Addr));
2370 static void OPC_6502_CD (void)
2371 /* Opcode $CD: CMP abs */
2375 Addr = ReadMemW (PC+1);
2376 CMP (AC, ReadMem (Addr));
2382 static void OPC_6502_CE (void)
2383 /* Opcode $CE: DEC abs */
2388 Addr = ReadMemW (PC+1);
2389 Val = ReadMem (Addr) - 1;
2390 WriteMem (Addr, Val);
2398 static void OPC_6502_CF (void)
2406 static void OPC_6502_D0 (void)
2407 /* Opcode $D0: BNE */
2409 BRANCH (!GET_ZF ());
2414 static void OPC_6502_D1 (void)
2415 /* Opcode $D1: CMP (zp),y */
2420 ZPAddr = ReadMem (PC+1);
2421 Addr = ReadMemW (ZPAddr);
2422 if (PAGE_CROSS (Addr, YR)) {
2425 CMP (AC, ReadMem (Addr + YR));
2431 static void OPC_6502_D2 (void)
2439 static void OPC_6502_D3 (void)
2447 static void OPC_6502_D4 (void)
2455 static void OPC_6502_D5 (void)
2456 /* Opcode $D5: CMP zp,x */
2458 unsigned char ZPAddr;
2460 ZPAddr = ReadMem (PC+1) + XR;
2461 CMP (AC, ReadMem (ZPAddr));
2467 static void OPC_6502_D6 (void)
2468 /* Opcode $D6: DEC zp,x */
2470 unsigned char ZPAddr;
2473 ZPAddr = ReadMem (PC+1) + XR;
2474 Val = ReadMem (ZPAddr) - 1;
2475 WriteMem (ZPAddr, Val);
2483 static void OPC_6502_D7 (void)
2491 static void OPC_6502_D8 (void)
2492 /* Opcode $D8: CLD */
2501 static void OPC_6502_D9 (void)
2502 /* Opcode $D9: CMP abs,y */
2506 Addr = ReadMemW (PC+1);
2507 if (PAGE_CROSS (Addr, YR)) {
2510 CMP (AC, ReadMem (Addr + YR));
2516 static void OPC_6502_DA (void)
2524 static void OPC_6502_DB (void)
2532 static void OPC_6502_DC (void)
2540 static void OPC_6502_DD (void)
2541 /* Opcode $DD: CMP abs,x */
2545 Addr = ReadMemW (PC+1);
2546 if (PAGE_CROSS (Addr, XR)) {
2549 CMP (AC, ReadMem (Addr + XR));
2555 static void OPC_6502_DE (void)
2556 /* Opcode $DE: DEC abs,x */
2561 Addr = ReadMemW (PC+1) + XR;
2562 Val = ReadMem (Addr) - 1;
2563 WriteMem (Addr, Val);
2571 static void OPC_6502_DF (void)
2579 static void OPC_6502_E0 (void)
2580 /* Opcode $E0: CPX #imm */
2583 CMP (XR, ReadMem (PC+1));
2589 static void OPC_6502_E1 (void)
2590 /* Opcode $E1: SBC (zp,x) */
2597 static void OPC_6502_E2 (void)
2605 static void OPC_6502_E3 (void)
2613 static void OPC_6502_E4 (void)
2614 /* Opcode $E4: CPX zp */
2616 unsigned char ZPAddr;
2618 ZPAddr = ReadMem (PC+1);
2619 CMP (XR, ReadMem (ZPAddr));
2625 static void OPC_6502_E5 (void)
2626 /* Opcode $E5: SBC zp */
2633 static void OPC_6502_E6 (void)
2634 /* Opcode $E6: INC zp */
2636 unsigned char ZPAddr;
2639 ZPAddr = ReadMem (PC+1);
2640 Val = ReadMem (ZPAddr) + 1;
2641 WriteMem (ZPAddr, Val);
2649 static void OPC_6502_E7 (void)
2657 static void OPC_6502_E8 (void)
2658 /* Opcode $E8: INX */
2669 static void OPC_6502_E9 (void)
2670 /* Opcode $E9: SBC #imm */
2677 static void OPC_6502_EA (void)
2678 /* Opcode $EA: NOP */
2680 /* This one is easy... */
2687 static void OPC_6502_EB (void)
2695 static void OPC_6502_EC (void)
2696 /* Opcode $EC: CPX abs */
2700 Addr = ReadMemW (PC+1);
2701 CMP (XR, ReadMem (Addr));
2707 static void OPC_6502_ED (void)
2708 /* Opcode $ED: SBC abs */
2715 static void OPC_6502_EE (void)
2716 /* Opcode $EE: INC abs */
2721 Addr = ReadMemW (PC+1);
2722 Val = ReadMem (Addr) + 1;
2723 WriteMem (Addr, Val);
2731 static void OPC_6502_EF (void)
2739 static void OPC_6502_F0 (void)
2740 /* Opcode $F0: BEQ */
2747 static void OPC_6502_F1 (void)
2748 /* Opcode $F1: SBC (zp),y */
2755 static void OPC_6502_F2 (void)
2763 static void OPC_6502_F3 (void)
2771 static void OPC_6502_F4 (void)
2779 static void OPC_6502_F5 (void)
2780 /* Opcode $F5: SBC zp,x */
2787 static void OPC_6502_F6 (void)
2788 /* Opcode $F6: INC zp,x */
2790 unsigned char ZPAddr;
2793 ZPAddr = ReadMem (PC+1) + XR;
2794 Val = ReadMem (ZPAddr) + 1;
2795 WriteMem (ZPAddr, Val);
2803 static void OPC_6502_F7 (void)
2811 static void OPC_6502_F8 (void)
2812 /* Opcode $F8: SED */
2819 static void OPC_6502_F9 (void)
2820 /* Opcode $F9: SBC abs,y */
2827 static void OPC_6502_FA (void)
2835 static void OPC_6502_FB (void)
2843 static void OPC_6502_FC (void)
2851 static void OPC_6502_FD (void)
2852 /* Opcode $FD: SBC abs,x */
2859 static void OPC_6502_FE (void)
2860 /* Opcode $FE: INC abs,x */
2865 Addr = ReadMemW (PC+1) + XR;
2866 Val = ReadMem (Addr) + 1;
2867 WriteMem (Addr, Val);
2875 static void OPC_6502_FF (void)
2883 /*****************************************************************************/
2885 /*****************************************************************************/
2889 /* Opcode handler table */
2890 typedef void (*OPCFunc) (void);
2891 static OPCFunc OPCTable[256] = {
3152 /*****************************************************************************/
3154 /*****************************************************************************/
3161 while (!CPUHalted) {
3163 /* Get the next opcode */
3164 unsigned char B = 0x00;
3170 TotalCycles += Cycles;