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 /*****************************************************************************/
51 /*****************************************************************************/
53 /*****************************************************************************/
58 unsigned char AC; /* Accumulator */
59 unsigned char XR; /* X register */
60 unsigned char YR; /* Y register */
61 unsigned char SR; /* Status register */
62 unsigned char SP; /* Stackpointer */
63 unsigned PC; /* Program counter */
65 /* Count the total number of cylcles */
66 unsigned Cycles; /* Cycles per insn */
67 unsigned long TotalCycles; /* Total cycles */
69 /* Allow the stack page to be changed */
70 static unsigned StackPage = 0x100;
72 /* Status register bits */
73 #define CF 0x01 /* Carry flag */
74 #define ZF 0x02 /* Zero flag */
75 #define IF 0x04 /* Interrupt flag */
76 #define DF 0x08 /* Decimal flag */
77 #define BF 0x10 /* Break flag */
78 #define OF 0x40 /* Overflow flag */
79 #define SF 0x80 /* Sign flag */
86 /*****************************************************************************/
87 /* Helper functions and macros */
88 /*****************************************************************************/
92 /* Return the flags as a boolean value (0/1) */
93 #define GET_CF() ((SR & CF) != 0)
94 #define GET_ZF() ((SR & ZF) != 0)
95 #define GET_IF() ((SR & IF) != 0)
96 #define GET_DF() ((SR & DF) != 0)
97 #define GET_BF() ((SR & BF) != 0)
98 #define GET_OF() ((SR & OF) != 0)
99 #define GET_SF() ((SR & SF) != 0)
101 /* Set the flags. The parameter is a boolean flag that says if the flag should be
104 #define SET_CF(f) do { if (f) { SR |= CF; } else { SR &= ~CF; } } while (0)
105 #define SET_ZF(f) do { if (f) { SR |= ZF; } else { SR &= ~ZF; } } while (0)
106 #define SET_IF(f) do { if (f) { SR |= IF; } else { SR &= ~IF; } } while (0)
107 #define SET_DF(f) do { if (f) { SR |= DF; } else { SR &= ~DF; } } while (0)
108 #define SET_BF(f) do { if (f) { SR |= BF; } else { SR &= ~BF; } } while (0)
109 #define SET_OF(f) do { if (f) { SR |= OF; } else { SR &= ~OF; } } while (0)
110 #define SET_SF(f) do { if (f) { SR |= SF; } else { SR &= ~SF; } } while (0)
112 /* Special test and set macros. The meaning of the parameter depends on the
113 * actual flag that should be set or reset.
115 #define TEST_ZF(v) SET_ZF (((v) & 0xFF) == 0)
116 #define TEST_SF(v) SET_SF (((v) & 0x80) != 0)
117 #define TEST_CF(v) SET_CF (((v) & 0xFF00) != 0)
119 /* Program counter halves */
120 #define PCL (PC & 0xFF)
121 #define PCH ((PC >> 8) & 0xFF)
123 /* Stack operations */
124 #define PUSH(Val) MemWriteByte (StackPage + SP--, Val)
125 #define POP() MemReadByte (StackPage + ++SP)
127 /* Test for page cross */
128 #define PAGE_CROSS(addr,offs) ((((addr) & 0xFF) + offs) >= 0x100)
131 #define AC_OP_IMM(op) \
133 AC = AC op MemReadByte (PC+1); \
139 #define AC_OP_ZP(op) \
141 AC = AC op MemReadByte (MemReadByte (PC+1));\
147 #define AC_OP_ZPX(op) \
148 unsigned char ZPAddr; \
150 ZPAddr = MemReadByte (PC+1) + XR; \
151 AC = AC op MemReadByte (ZPAddr); \
157 #define AC_OP_ZPY(op) \
158 unsigned char ZPAddr; \
160 ZPAddr = MemReadByte (PC+1) + YR; \
161 AC = AC op MemReadByte (ZPAddr); \
167 #define AC_OP_ABS(op) \
170 Addr = MemReadWord (PC+1); \
171 AC = AC op MemReadByte (Addr); \
177 #define AC_OP_ABSX(op) \
180 Addr = MemReadWord (PC+1); \
181 if (PAGE_CROSS (Addr, XR)) { \
184 AC = AC | MemReadByte (Addr + XR); \
190 #define AC_OP_ABSY(op) \
193 Addr = MemReadWord (PC+1); \
194 if (PAGE_CROSS (Addr, YR)) { \
197 AC = AC | MemReadByte (Addr + YR); \
203 #define AC_OP_ZPXIND(op) \
204 unsigned char ZPAddr; \
207 ZPAddr = MemReadByte (PC+1) + XR; \
208 Addr = MemReadZPWord (ZPAddr); \
209 AC = AC op MemReadByte (Addr); \
215 #define AC_OP_ZPINDY(op) \
216 unsigned char ZPAddr; \
219 ZPAddr = MemReadByte (PC+1); \
220 Addr = MemReadZPWord (ZPAddr) + YR; \
221 AC = AC op MemReadByte (Addr); \
232 unsigned char rhs = v; \
233 Val = AC + rhs + GET_CF (); \
234 AC = (unsigned char) Val; \
238 SET_OF (!((AC ^ rhs) & 0x80) && \
239 ((AC ^ Val) & 0x80)); \
243 #define BRANCH(cond) \
247 unsigned char OldPCH; \
249 Offs = (signed char) MemReadByte (PC+1);\
251 PC += 2 + (int) Offs; \
252 if (PCH != OldPCH) { \
262 unsigned Result = v1 - v2; \
263 TEST_ZF (Result & 0xFF); \
265 SET_CF (Result <= 0xFF); \
284 SET_CF (Val & 0x01); \
295 unsigned char rhs = v; \
296 Val = AC - rhs - (!GET_CF ()); \
297 AC = (unsigned char) Val; \
300 SET_CF (Val <= 0xFF); \
301 SET_OF (((AC^rhs) & (AC^Val) & 0x80)); \
306 /*****************************************************************************/
307 /* Helper functions */
308 /*****************************************************************************/
312 static void OPC_Illegal (void) attribute ((noreturn));
313 static void OPC_Illegal (void)
315 fprintf (stderr, "Illegal: $%02X\n", MemReadByte (PC));
321 static void NotImplemented (void) attribute ((noreturn));
322 static void NotImplemented (void)
324 fprintf (stderr, "Not implemented: $%02X\n", MemReadByte (PC));
330 /*****************************************************************************/
332 /*****************************************************************************/
336 static void OPC_6502_00 (void)
337 /* Opcode $00: BRK */
346 PC = MemReadWord (0xFFFE);
351 static void OPC_6502_01 (void)
352 /* Opcode $01: ORA (ind,x) */
359 static void OPC_6502_05 (void)
360 /* Opcode $05: ORA zp */
367 static void OPC_6502_06 (void)
368 /* Opcode $06: ASL zp */
370 unsigned char ZPAddr;
373 ZPAddr = MemReadByte (PC+1);
374 Val = MemReadByte (ZPAddr) << 1;
375 MemWriteByte (ZPAddr, (unsigned char) Val);
376 TEST_ZF (Val & 0xFF);
378 SET_CF (Val & 0x100);
384 static void OPC_6502_08 (void)
385 /* Opcode $08: PHP */
394 static void OPC_6502_09 (void)
395 /* Opcode $09: ORA #imm */
402 static void OPC_6502_0A (void)
403 /* Opcode $0A: ASL a */
408 AC = (unsigned char) Val;
409 TEST_ZF (Val & 0xFF);
411 SET_CF (Val & 0x100);
417 static void OPC_6502_0D (void)
418 /* Opcode $0D: ORA abs */
425 static void OPC_6502_0E (void)
426 /* Opcode $0E: ALS abs */
431 Addr = MemReadWord (PC+1);
432 Val = MemReadByte (Addr) << 1;
433 MemWriteByte (Addr, (unsigned char) Val);
434 TEST_ZF (Val & 0xFF);
436 SET_CF (Val & 0x100);
442 static void OPC_6502_10 (void)
443 /* Opcode $10: BPL */
450 static void OPC_6502_11 (void)
451 /* Opcode $11: ORA (zp),y */
458 static void OPC_6502_15 (void)
459 /* Opcode $15: ORA zp,x */
466 static void OPC_6502_16 (void)
467 /* Opcode $16: ASL zp,x */
469 unsigned char ZPAddr;
472 ZPAddr = MemReadByte (PC+1) + XR;
473 Val = MemReadByte (ZPAddr) << 1;
474 MemWriteByte (ZPAddr, (unsigned char) Val);
475 TEST_ZF (Val & 0xFF);
477 SET_CF (Val & 0x100);
483 static void OPC_6502_18 (void)
484 /* Opcode $18: CLC */
493 static void OPC_6502_19 (void)
494 /* Opcode $19: ORA abs,y */
501 static void OPC_6502_1D (void)
502 /* Opcode $1D: ORA abs,x */
509 static void OPC_6502_1E (void)
510 /* Opcode $1E: ASL abs,x */
515 Addr = MemReadWord (PC+1) + XR;
516 Val = MemReadByte (Addr) << 1;
517 MemWriteByte (Addr, (unsigned char) Val);
518 TEST_ZF (Val & 0xFF);
520 SET_CF (Val & 0x100);
526 static void OPC_6502_20 (void)
527 /* Opcode $20: JSR */
531 Addr = MemReadWord (PC+1);
540 static void OPC_6502_21 (void)
541 /* Opcode $21: AND (zp,x) */
548 static void OPC_6502_24 (void)
549 /* Opcode $24: BIT zp */
551 unsigned char ZPAddr;
554 ZPAddr = MemReadByte (PC+1);
555 Val = MemReadByte (ZPAddr);
558 SET_ZF ((Val & AC) == 0);
564 static void OPC_6502_25 (void)
565 /* Opcode $25: AND zp */
572 static void OPC_6502_26 (void)
573 /* Opcode $26: ROL zp */
575 unsigned char ZPAddr;
578 ZPAddr = MemReadByte (PC+1);
579 Val = MemReadByte (ZPAddr);
581 MemWriteByte (ZPAddr, Val);
587 static void OPC_6502_28 (void)
588 /* Opcode $28: PLP */
597 static void OPC_6502_29 (void)
598 /* Opcode $29: AND #imm */
605 static void OPC_6502_2A (void)
606 /* Opcode $2A: ROL a */
612 AC = (unsigned char) Val;
618 static void OPC_6502_2C (void)
619 /* Opcode $2C: BIT abs */
624 Addr = MemReadByte (PC+1);
625 Val = MemReadByte (Addr);
628 SET_ZF ((Val & AC) == 0);
634 static void OPC_6502_2D (void)
635 /* Opcode $2D: AND abs */
642 static void OPC_6502_2E (void)
643 /* Opcode $2E: ROL abs */
648 Addr = MemReadWord (PC+1);
649 Val = MemReadByte (Addr);
651 MemWriteByte (Addr, Val);
657 static void OPC_6502_30 (void)
658 /* Opcode $30: BMI */
665 static void OPC_6502_31 (void)
666 /* Opcode $31: AND (zp),y */
673 static void OPC_6502_35 (void)
674 /* Opcode $35: AND zp,x */
681 static void OPC_6502_36 (void)
682 /* Opcode $36: ROL zp,x */
684 unsigned char ZPAddr;
687 ZPAddr = MemReadByte (PC+1) + XR;
688 Val = MemReadByte (ZPAddr);
690 MemWriteByte (ZPAddr, Val);
696 static void OPC_6502_38 (void)
697 /* Opcode $38: SEC */
706 static void OPC_6502_39 (void)
707 /* Opcode $39: AND abs,y */
714 static void OPC_6502_3D (void)
715 /* Opcode $3D: AND abs,x */
722 static void OPC_6502_3E (void)
723 /* Opcode $3E: ROL abs,x */
728 Addr = MemReadWord (PC+1) + XR;
729 Val = MemReadByte (Addr);
731 MemWriteByte (Addr, Val);
737 static void OPC_6502_40 (void)
738 /* Opcode $40: RTI */
742 PC = POP (); /* PCL */
743 PC |= (POP () << 8); /* PCH */
748 static void OPC_6502_41 (void)
749 /* Opcode $41: EOR (zp,x) */
756 static void OPC_6502_45 (void)
757 /* Opcode $45: EOR zp */
764 static void OPC_6502_46 (void)
765 /* Opcode $46: LSR zp */
767 unsigned char ZPAddr;
770 ZPAddr = MemReadByte (PC+1);
771 Val = MemReadByte (ZPAddr);
774 MemWriteByte (ZPAddr, Val);
782 static void OPC_6502_48 (void)
783 /* Opcode $48: PHA */
792 static void OPC_6502_49 (void)
793 /* Opcode $49: EOR #imm */
800 static void OPC_6502_4A (void)
801 /* Opcode $4A: LSR a */
813 static void OPC_6502_4C (void)
814 /* Opcode $4C: JMP abs */
817 PC = MemReadWord (PC+1);
822 static void OPC_6502_4D (void)
823 /* Opcode $4D: EOR abs */
830 static void OPC_6502_4E (void)
831 /* Opcode $4E: LSR abs */
836 Addr = MemReadWord (PC+1);
837 Val = MemReadByte (Addr);
840 MemWriteByte (Addr, Val);
848 static void OPC_6502_50 (void)
849 /* Opcode $50: BVC */
856 static void OPC_6502_51 (void)
857 /* Opcode $51: EOR (zp),y */
864 static void OPC_6502_55 (void)
865 /* Opcode $55: EOR zp,x */
872 static void OPC_6502_56 (void)
873 /* Opcode $56: LSR zp,x */
875 unsigned char ZPAddr;
878 ZPAddr = MemReadByte (PC+1) + XR;
879 Val = MemReadByte (ZPAddr);
882 MemWriteByte (ZPAddr, Val);
890 static void OPC_6502_58 (void)
891 /* Opcode $58: CLI */
900 static void OPC_6502_59 (void)
901 /* Opcode $59: EOR abs,y */
908 static void OPC_6502_5D (void)
909 /* Opcode $5D: EOR abs,x */
916 static void OPC_6502_5E (void)
917 /* Opcode $5E: LSR abs,x */
922 Addr = MemReadWord (PC+1) + XR;
923 Val = MemReadByte (Addr);
926 MemWriteByte (Addr, Val);
934 static void OPC_6502_60 (void)
935 /* Opcode $60: RTS */
938 PC = POP (); /* PCL */
939 PC |= (POP () << 8); /* PCH */
945 static void OPC_6502_61 (void)
946 /* Opcode $61: ADC (zp,x) */
948 unsigned char ZPAddr;
951 ZPAddr = MemReadByte (PC+1) + XR;
952 Addr = MemReadZPWord (ZPAddr);
953 ADC (MemReadByte (Addr));
959 static void OPC_6502_65 (void)
960 /* Opcode $65: ADC zp */
962 unsigned char ZPAddr;
964 ZPAddr = MemReadByte (PC+1);
965 ADC (MemReadByte (ZPAddr));
971 static void OPC_6502_66 (void)
972 /* Opcode $66: ROR zp */
974 unsigned char ZPAddr;
977 ZPAddr = MemReadByte (PC+1);
978 Val = MemReadByte (ZPAddr);
980 MemWriteByte (ZPAddr, Val);
986 static void OPC_6502_68 (void)
987 /* Opcode $68: PLA */
998 static void OPC_6502_69 (void)
999 /* Opcode $69: ADC #imm */
1002 ADC (MemReadByte (PC+1));
1008 static void OPC_6502_6A (void)
1009 /* Opcode $6A: ROR a */
1015 AC = (unsigned char) Val;
1021 static void OPC_6502_6C (void)
1022 /* Opcode $6C: JMP (ind) */
1026 Addr = MemReadWord (PC+1);
1027 if (CPU == CPU_6502) {
1028 /* Emulate the 6502 bug */
1029 PC = MemReadByte (Addr);
1030 Addr = (Addr & 0xFF00) | ((Addr + 1) & 0xFF);
1031 PC |= (MemReadByte (Addr) << 8);
1033 /* 65C02 and above have this bug fixed */
1034 PC = MemReadWord (Addr);
1041 static void OPC_6502_6D (void)
1042 /* Opcode $6D: ADC abs */
1046 Addr = MemReadWord (PC+1);
1047 ADC (MemReadByte (Addr));
1053 static void OPC_6502_6E (void)
1054 /* Opcode $6E: ROR abs */
1059 Addr = MemReadWord (PC+1);
1060 Val = MemReadByte (Addr);
1062 MemWriteByte (Addr, Val);
1068 static void OPC_6502_70 (void)
1069 /* Opcode $70: BVS */
1076 static void OPC_6502_71 (void)
1077 /* Opcode $71: ADC (zp),y */
1079 unsigned char ZPAddr;
1082 ZPAddr = MemReadByte (PC+1);
1083 Addr = MemReadZPWord (ZPAddr);
1084 if (PAGE_CROSS (Addr, YR)) {
1087 ADC (MemReadByte (Addr + YR));
1093 static void OPC_6502_75 (void)
1094 /* Opcode $75: ADC zp,x */
1096 unsigned char ZPAddr;
1098 ZPAddr = MemReadByte (PC+1) + XR;
1099 ADC (MemReadByte (ZPAddr));
1105 static void OPC_6502_76 (void)
1106 /* Opcode $76: ROR zp,x */
1108 unsigned char ZPAddr;
1111 ZPAddr = MemReadByte (PC+1) + XR;
1112 Val = MemReadByte (ZPAddr);
1114 MemWriteByte (ZPAddr, Val);
1120 static void OPC_6502_78 (void)
1121 /* Opcode $78: SEI */
1130 static void OPC_6502_79 (void)
1131 /* Opcode $79: ADC abs,y */
1135 Addr = MemReadWord (PC+1);
1136 if (PAGE_CROSS (Addr, YR)) {
1139 ADC (MemReadByte (Addr + YR));
1145 static void OPC_6502_7D (void)
1146 /* Opcode $7D: ADC abs,x */
1150 Addr = MemReadWord (PC+1);
1151 if (PAGE_CROSS (Addr, XR)) {
1154 ADC (MemReadByte (Addr + XR));
1160 static void OPC_6502_7E (void)
1161 /* Opcode $7E: ROR abs,x */
1166 Addr = MemReadByte (PC+1) + XR;
1167 Val = MemReadByte (Addr);
1169 MemWriteByte (Addr, Val);
1175 static void OPC_6502_81 (void)
1176 /* Opcode $81: STA (zp,x) */
1178 unsigned char ZPAddr;
1181 ZPAddr = MemReadByte (PC+1) + XR;
1182 Addr = MemReadZPWord (ZPAddr);
1183 MemWriteByte (Addr, AC);
1189 static void OPC_6502_84 (void)
1190 /* Opcode $84: STY zp */
1192 unsigned char ZPAddr;
1194 ZPAddr = MemReadByte (PC+1);
1195 MemWriteByte (ZPAddr, YR);
1201 static void OPC_6502_85 (void)
1202 /* Opcode $85: STA zp */
1204 unsigned char ZPAddr;
1206 ZPAddr = MemReadByte (PC+1);
1207 MemWriteByte (ZPAddr, AC);
1213 static void OPC_6502_86 (void)
1214 /* Opcode $86: STX zp */
1216 unsigned char ZPAddr;
1218 ZPAddr = MemReadByte (PC+1);
1219 MemWriteByte (ZPAddr, XR);
1225 static void OPC_6502_88 (void)
1226 /* Opcode $88: DEY */
1237 static void OPC_6502_8A (void)
1238 /* Opcode $8A: TXA */
1249 static void OPC_6502_8C (void)
1250 /* Opcode $8C: STY abs */
1254 Addr = MemReadWord (PC+1);
1255 MemWriteByte (Addr, YR);
1261 static void OPC_6502_8D (void)
1262 /* Opcode $8D: STA abs */
1266 Addr = MemReadWord (PC+1);
1267 MemWriteByte (Addr, AC);
1273 static void OPC_6502_8E (void)
1274 /* Opcode $8E: STX abs */
1278 Addr = MemReadWord (PC+1);
1279 MemWriteByte (Addr, XR);
1285 static void OPC_6502_90 (void)
1286 /* Opcode $90: BCC */
1288 BRANCH (!GET_CF ());
1293 static void OPC_6502_91 (void)
1294 /* Opcode $91: sta (zp),y */
1296 unsigned char ZPAddr;
1299 ZPAddr = MemReadByte (PC+1);
1300 Addr = MemReadZPWord (ZPAddr) + YR;
1301 MemWriteByte (Addr, AC);
1307 static void OPC_6502_94 (void)
1308 /* Opcode $94: STY zp,x */
1310 unsigned char ZPAddr;
1312 ZPAddr = MemReadByte (PC+1) + XR;
1313 MemWriteByte (ZPAddr, YR);
1319 static void OPC_6502_95 (void)
1320 /* Opcode $95: STA zp,x */
1322 unsigned char ZPAddr;
1324 ZPAddr = MemReadByte (PC+1) + XR;
1325 MemWriteByte (ZPAddr, AC);
1331 static void OPC_6502_96 (void)
1332 /* Opcode $96: stx zp,y */
1334 unsigned char ZPAddr;
1336 ZPAddr = MemReadByte (PC+1) + YR;
1337 MemWriteByte (ZPAddr, XR);
1343 static void OPC_6502_98 (void)
1344 /* Opcode $98: TYA */
1355 static void OPC_6502_99 (void)
1356 /* Opcode $99: STA abs,y */
1360 Addr = MemReadWord (PC+1) + YR;
1361 MemWriteByte (Addr, AC);
1367 static void OPC_6502_9A (void)
1368 /* Opcode $9A: TXS */
1377 static void OPC_6502_9D (void)
1378 /* Opcode $9D: STA abs,x */
1382 Addr = MemReadWord (PC+1) + XR;
1383 MemWriteByte (Addr, AC);
1389 static void OPC_6502_A0 (void)
1390 /* Opcode $A0: LDY #imm */
1393 YR = MemReadByte (PC+1);
1401 static void OPC_6502_A1 (void)
1402 /* Opcode $A1: LDA (zp,x) */
1404 unsigned char ZPAddr;
1407 ZPAddr = MemReadByte (PC+1) + XR;
1408 Addr = MemReadZPWord (ZPAddr);
1409 AC = MemReadByte (Addr);
1417 static void OPC_6502_A2 (void)
1418 /* Opcode $A2: LDX #imm */
1421 XR = MemReadByte (PC+1);
1429 static void OPC_6502_A4 (void)
1430 /* Opcode $A4: LDY zp */
1432 unsigned char ZPAddr;
1434 ZPAddr = MemReadByte (PC+1);
1435 YR = MemReadByte (ZPAddr);
1443 static void OPC_6502_A5 (void)
1444 /* Opcode $A5: LDA zp */
1446 unsigned char ZPAddr;
1448 ZPAddr = MemReadByte (PC+1);
1449 AC = MemReadByte (ZPAddr);
1457 static void OPC_6502_A6 (void)
1458 /* Opcode $A6: LDX zp */
1460 unsigned char ZPAddr;
1462 ZPAddr = MemReadByte (PC+1);
1463 XR = MemReadByte (ZPAddr);
1471 static void OPC_6502_A8 (void)
1472 /* Opcode $A8: TAY */
1483 static void OPC_6502_A9 (void)
1484 /* Opcode $A9: LDA #imm */
1487 AC = MemReadByte (PC+1);
1495 static void OPC_6502_AA (void)
1496 /* Opcode $AA: TAX */
1507 static void OPC_6502_AC (void)
1508 /* Opcode $AC: LDY abs */
1512 Addr = MemReadWord (PC+1);
1513 YR = MemReadByte (Addr);
1521 static void OPC_6502_AD (void)
1522 /* Opcode $AD: LDA abs */
1526 Addr = MemReadWord (PC+1);
1527 AC = MemReadByte (Addr);
1535 static void OPC_6502_AE (void)
1536 /* Opcode $AE: LDX abs */
1540 Addr = MemReadWord (PC+1);
1541 XR = MemReadByte (Addr);
1549 static void OPC_6502_B0 (void)
1550 /* Opcode $B0: BCS */
1557 static void OPC_6502_B1 (void)
1558 /* Opcode $B1: LDA (zp),y */
1560 unsigned char ZPAddr;
1563 ZPAddr = MemReadByte (PC+1);
1564 Addr = MemReadZPWord (ZPAddr);
1565 if (PAGE_CROSS (Addr, YR)) {
1568 AC = MemReadByte (Addr + YR);
1576 static void OPC_6502_B4 (void)
1577 /* Opcode $B4: LDY zp,x */
1579 unsigned char ZPAddr;
1581 ZPAddr = MemReadByte (PC+1) + XR;
1582 YR = MemReadByte (ZPAddr);
1590 static void OPC_6502_B5 (void)
1591 /* Opcode $B5: LDA zp,x */
1593 unsigned char ZPAddr;
1595 ZPAddr = MemReadByte (PC+1) + XR;
1596 AC = MemReadByte (ZPAddr);
1604 static void OPC_6502_B6 (void)
1605 /* Opcode $B6: LDX zp,y */
1607 unsigned char ZPAddr;
1609 ZPAddr = MemReadByte (PC+1) + YR;
1610 XR = MemReadByte (ZPAddr);
1618 static void OPC_6502_B8 (void)
1619 /* Opcode $B8: CLV */
1628 static void OPC_6502_B9 (void)
1629 /* Opcode $B9: LDA abs,y */
1633 Addr = MemReadWord (PC+1);
1634 if (PAGE_CROSS (Addr, YR)) {
1637 AC = MemReadByte (Addr + YR);
1645 static void OPC_6502_BA (void)
1646 /* Opcode $BA: TSX */
1657 static void OPC_6502_BC (void)
1658 /* Opcode $BC: LDY abs,x */
1662 Addr = MemReadWord (PC+1);
1663 if (PAGE_CROSS (Addr, XR)) {
1666 YR = MemReadByte (Addr + XR);
1674 static void OPC_6502_BD (void)
1675 /* Opcode $BD: LDA abs,x */
1679 Addr = MemReadWord (PC+1);
1680 if (PAGE_CROSS (Addr, XR)) {
1683 AC = MemReadByte (Addr + XR);
1691 static void OPC_6502_BE (void)
1692 /* Opcode $BE: LDX abs,y */
1696 Addr = MemReadWord (PC+1);
1697 if (PAGE_CROSS (Addr, YR)) {
1700 XR = MemReadByte (Addr + YR);
1708 static void OPC_6502_C0 (void)
1709 /* Opcode $C0: CPY #imm */
1712 CMP (YR, MemReadByte (PC+1));
1718 static void OPC_6502_C1 (void)
1719 /* Opcode $C1: CMP (zp,x) */
1721 unsigned char ZPAddr;
1724 ZPAddr = MemReadByte (PC+1) + XR;
1725 Addr = MemReadZPWord (ZPAddr);
1726 CMP (AC, MemReadByte (Addr));
1732 static void OPC_6502_C4 (void)
1733 /* Opcode $C4: CPY zp */
1735 unsigned char ZPAddr;
1737 ZPAddr = MemReadByte (PC+1);
1738 CMP (YR, MemReadByte (ZPAddr));
1744 static void OPC_6502_C5 (void)
1745 /* Opcode $C5: CMP zp */
1747 unsigned char ZPAddr;
1749 ZPAddr = MemReadByte (PC+1);
1750 CMP (AC, MemReadByte (ZPAddr));
1756 static void OPC_6502_C6 (void)
1757 /* Opcode $C6: DEC zp */
1759 unsigned char ZPAddr;
1762 ZPAddr = MemReadByte (PC+1);
1763 Val = MemReadByte (ZPAddr) - 1;
1764 MemWriteByte (ZPAddr, Val);
1772 static void OPC_6502_C8 (void)
1773 /* Opcode $C8: INY */
1784 static void OPC_6502_C9 (void)
1785 /* Opcode $C9: CMP #imm */
1788 CMP (AC, MemReadByte (PC+1));
1794 static void OPC_6502_CA (void)
1795 /* Opcode $CA: DEX */
1806 static void OPC_6502_CC (void)
1807 /* Opcode $CC: CPY abs */
1811 Addr = MemReadWord (PC+1);
1812 CMP (YR, MemReadByte (Addr));
1818 static void OPC_6502_CD (void)
1819 /* Opcode $CD: CMP abs */
1823 Addr = MemReadWord (PC+1);
1824 CMP (AC, MemReadByte (Addr));
1830 static void OPC_6502_CE (void)
1831 /* Opcode $CE: DEC abs */
1836 Addr = MemReadWord (PC+1);
1837 Val = MemReadByte (Addr) - 1;
1838 MemWriteByte (Addr, Val);
1846 static void OPC_6502_D0 (void)
1847 /* Opcode $D0: BNE */
1849 BRANCH (!GET_ZF ());
1854 static void OPC_6502_D1 (void)
1855 /* Opcode $D1: CMP (zp),y */
1860 ZPAddr = MemReadByte (PC+1);
1861 Addr = MemReadWord (ZPAddr);
1862 if (PAGE_CROSS (Addr, YR)) {
1865 CMP (AC, MemReadByte (Addr + YR));
1871 static void OPC_6502_D5 (void)
1872 /* Opcode $D5: CMP zp,x */
1874 unsigned char ZPAddr;
1876 ZPAddr = MemReadByte (PC+1) + XR;
1877 CMP (AC, MemReadByte (ZPAddr));
1883 static void OPC_6502_D6 (void)
1884 /* Opcode $D6: DEC zp,x */
1886 unsigned char ZPAddr;
1889 ZPAddr = MemReadByte (PC+1) + XR;
1890 Val = MemReadByte (ZPAddr) - 1;
1891 MemWriteByte (ZPAddr, Val);
1899 static void OPC_6502_D8 (void)
1900 /* Opcode $D8: CLD */
1909 static void OPC_6502_D9 (void)
1910 /* Opcode $D9: CMP abs,y */
1914 Addr = MemReadWord (PC+1);
1915 if (PAGE_CROSS (Addr, YR)) {
1918 CMP (AC, MemReadByte (Addr + YR));
1924 static void OPC_6502_DD (void)
1925 /* Opcode $DD: CMP abs,x */
1929 Addr = MemReadWord (PC+1);
1930 if (PAGE_CROSS (Addr, XR)) {
1933 CMP (AC, MemReadByte (Addr + XR));
1939 static void OPC_6502_DE (void)
1940 /* Opcode $DE: DEC abs,x */
1945 Addr = MemReadWord (PC+1) + XR;
1946 Val = MemReadByte (Addr) - 1;
1947 MemWriteByte (Addr, Val);
1955 static void OPC_6502_E0 (void)
1956 /* Opcode $E0: CPX #imm */
1959 CMP (XR, MemReadByte (PC+1));
1965 static void OPC_6502_E1 (void)
1966 /* Opcode $E1: SBC (zp,x) */
1968 unsigned char ZPAddr;
1971 ZPAddr = MemReadByte (PC+1) + XR;
1972 Addr = MemReadZPWord (ZPAddr);
1973 SBC (MemReadByte (Addr));
1979 static void OPC_6502_E4 (void)
1980 /* Opcode $E4: CPX zp */
1982 unsigned char ZPAddr;
1984 ZPAddr = MemReadByte (PC+1);
1985 CMP (XR, MemReadByte (ZPAddr));
1991 static void OPC_6502_E5 (void)
1992 /* Opcode $E5: SBC zp */
1994 unsigned char ZPAddr;
1996 ZPAddr = MemReadByte (PC+1);
1997 SBC (MemReadByte (ZPAddr));
2003 static void OPC_6502_E6 (void)
2004 /* Opcode $E6: INC zp */
2006 unsigned char ZPAddr;
2009 ZPAddr = MemReadByte (PC+1);
2010 Val = MemReadByte (ZPAddr) + 1;
2011 MemWriteByte (ZPAddr, Val);
2019 static void OPC_6502_E8 (void)
2020 /* Opcode $E8: INX */
2031 static void OPC_6502_E9 (void)
2032 /* Opcode $E9: SBC #imm */
2035 SBC (MemReadByte (PC+1));
2041 static void OPC_6502_EA (void)
2042 /* Opcode $EA: NOP */
2044 /* This one is easy... */
2051 static void OPC_6502_EC (void)
2052 /* Opcode $EC: CPX abs */
2056 Addr = MemReadWord (PC+1);
2057 CMP (XR, MemReadByte (Addr));
2063 static void OPC_6502_ED (void)
2064 /* Opcode $ED: SBC abs */
2068 Addr = MemReadWord (PC+1);
2069 SBC (MemReadByte (Addr));
2075 static void OPC_6502_EE (void)
2076 /* Opcode $EE: INC abs */
2081 Addr = MemReadWord (PC+1);
2082 Val = MemReadByte (Addr) + 1;
2083 MemWriteByte (Addr, Val);
2091 static void OPC_6502_F0 (void)
2092 /* Opcode $F0: BEQ */
2099 static void OPC_6502_F1 (void)
2100 /* Opcode $F1: SBC (zp),y */
2102 unsigned char ZPAddr;
2105 ZPAddr = MemReadByte (PC+1);
2106 Addr = MemReadZPWord (ZPAddr);
2107 if (PAGE_CROSS (Addr, YR)) {
2110 SBC (MemReadByte (Addr + YR));
2116 static void OPC_6502_F5 (void)
2117 /* Opcode $F5: SBC zp,x */
2119 unsigned char ZPAddr;
2121 ZPAddr = MemReadByte (PC+1) + XR;
2122 SBC (MemReadByte (ZPAddr));
2128 static void OPC_6502_F6 (void)
2129 /* Opcode $F6: INC zp,x */
2131 unsigned char ZPAddr;
2134 ZPAddr = MemReadByte (PC+1) + XR;
2135 Val = MemReadByte (ZPAddr) + 1;
2136 MemWriteByte (ZPAddr, Val);
2144 static void OPC_6502_F8 (void)
2145 /* Opcode $F8: SED */
2152 static void OPC_6502_F9 (void)
2153 /* Opcode $F9: SBC abs,y */
2157 Addr = MemReadWord (PC+1);
2158 if (PAGE_CROSS (Addr, YR)) {
2161 SBC (MemReadByte (Addr + YR));
2167 static void OPC_6502_FD (void)
2168 /* Opcode $FD: SBC abs,x */
2172 Addr = MemReadWord (PC+1);
2173 if (PAGE_CROSS (Addr, XR)) {
2176 SBC (MemReadByte (Addr + XR));
2182 static void OPC_6502_FE (void)
2183 /* Opcode $FE: INC abs,x */
2188 Addr = MemReadWord (PC+1) + XR;
2189 Val = MemReadByte (Addr) + 1;
2190 MemWriteByte (Addr, Val);
2198 /*****************************************************************************/
2200 /*****************************************************************************/
2204 /* Opcode handler table */
2205 typedef void (*OPCFunc) (void);
2206 static OPCFunc OPCTable[256] = {
2467 /*****************************************************************************/
2469 /*****************************************************************************/
2474 /* Initialize the CPU */
2476 PC = MemReadWord (0xFFFC);
2489 /* Generate an IRQ */
2496 /* Generate an NMI */
2505 while (!CPUHalted) {
2507 /* Get the next opcode */
2508 unsigned char B = MemReadByte (PC);
2514 TotalCycles += Cycles;