1 /*****************************************************************************/
5 /* CPU core for the 6502 simulator */
9 /* (C) 2002-2003 Ullrich von Bassewitz */
10 /* Römerstrasse 52 */
11 /* D-70794 Filderstadt */
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 /*****************************************************************************/
52 /*****************************************************************************/
54 /*****************************************************************************/
59 unsigned char AC; /* Accumulator */
60 unsigned char XR; /* X register */
61 unsigned char YR; /* Y register */
62 unsigned char SR; /* Status register */
63 unsigned char SP; /* Stackpointer */
64 unsigned PC; /* Program counter */
66 /* Count the total number of cylcles */
67 unsigned Cycles; /* Cycles per insn */
68 unsigned long TotalCycles; /* Total cycles */
70 /* Allow the stack page to be changed */
71 static unsigned StackPage = 0x100;
73 /* Status register bits */
74 #define CF 0x01 /* Carry flag */
75 #define ZF 0x02 /* Zero flag */
76 #define IF 0x04 /* Interrupt flag */
77 #define DF 0x08 /* Decimal flag */
78 #define BF 0x10 /* Break flag */
79 #define OF 0x40 /* Overflow flag */
80 #define SF 0x80 /* Sign flag */
87 /*****************************************************************************/
88 /* Helper functions and macros */
89 /*****************************************************************************/
93 /* Return the flags as a boolean value (0/1) */
94 #define GET_CF() ((SR & CF) != 0)
95 #define GET_ZF() ((SR & ZF) != 0)
96 #define GET_IF() ((SR & IF) != 0)
97 #define GET_DF() ((SR & DF) != 0)
98 #define GET_BF() ((SR & BF) != 0)
99 #define GET_OF() ((SR & OF) != 0)
100 #define GET_SF() ((SR & SF) != 0)
102 /* Set the flags. The parameter is a boolean flag that says if the flag should be
105 #define SET_CF(f) do { if (f) { SR |= CF; } else { SR &= ~CF; } } while (0)
106 #define SET_ZF(f) do { if (f) { SR |= ZF; } else { SR &= ~ZF; } } while (0)
107 #define SET_IF(f) do { if (f) { SR |= IF; } else { SR &= ~IF; } } while (0)
108 #define SET_DF(f) do { if (f) { SR |= DF; } else { SR &= ~DF; } } while (0)
109 #define SET_BF(f) do { if (f) { SR |= BF; } else { SR &= ~BF; } } while (0)
110 #define SET_OF(f) do { if (f) { SR |= OF; } else { SR &= ~OF; } } while (0)
111 #define SET_SF(f) do { if (f) { SR |= SF; } else { SR &= ~SF; } } while (0)
113 /* Special test and set macros. The meaning of the parameter depends on the
114 * actual flag that should be set or reset.
116 #define TEST_ZF(v) SET_ZF (((v) & 0xFF) == 0)
117 #define TEST_SF(v) SET_SF (((v) & 0x80) != 0)
118 #define TEST_CF(v) SET_CF (((v) & 0xFF00) != 0)
120 /* Program counter halves */
121 #define PCL (PC & 0xFF)
122 #define PCH ((PC >> 8) & 0xFF)
124 /* Stack operations */
125 #define PUSH(Val) MemWriteByte (StackPage + SP--, Val)
126 #define POP() MemReadByte (StackPage + ++SP)
128 /* Test for page cross */
129 #define PAGE_CROSS(addr,offs) ((((addr) & 0xFF) + offs) >= 0x100)
132 #define AC_OP_IMM(op) \
134 AC = AC op MemReadByte (PC+1); \
140 #define AC_OP_ZP(op) \
142 AC = AC op MemReadByte (MemReadByte (PC+1));\
148 #define AC_OP_ZPX(op) \
149 unsigned char ZPAddr; \
151 ZPAddr = MemReadByte (PC+1) + XR; \
152 AC = AC op MemReadByte (ZPAddr); \
158 #define AC_OP_ZPY(op) \
159 unsigned char ZPAddr; \
161 ZPAddr = MemReadByte (PC+1) + YR; \
162 AC = AC op MemReadByte (ZPAddr); \
168 #define AC_OP_ABS(op) \
171 Addr = MemReadWord (PC+1); \
172 AC = AC op MemReadByte (Addr); \
178 #define AC_OP_ABSX(op) \
181 Addr = MemReadWord (PC+1); \
182 if (PAGE_CROSS (Addr, XR)) { \
185 AC = AC | MemReadByte (Addr + XR); \
191 #define AC_OP_ABSY(op) \
194 Addr = MemReadWord (PC+1); \
195 if (PAGE_CROSS (Addr, YR)) { \
198 AC = AC | MemReadByte (Addr + YR); \
204 #define AC_OP_ZPXIND(op) \
205 unsigned char ZPAddr; \
208 ZPAddr = MemReadByte (PC+1) + XR; \
209 Addr = MemReadZPWord (ZPAddr); \
210 AC = AC op MemReadByte (Addr); \
216 #define AC_OP_ZPINDY(op) \
217 unsigned char ZPAddr; \
220 ZPAddr = MemReadByte (PC+1); \
221 Addr = MemReadZPWord (ZPAddr) + YR; \
222 AC = AC op MemReadByte (Addr); \
230 Warning ("Decimal mode not available"); \
233 unsigned char rhs = v; \
234 Val = AC + rhs + GET_CF (); \
235 AC = (unsigned char) Val; \
239 SET_OF (!((AC ^ rhs) & 0x80) && \
240 ((AC ^ Val) & 0x80)); \
244 #define BRANCH(cond) \
248 unsigned char OldPCH; \
250 Offs = (signed char) MemReadByte (PC+1);\
252 PC += 2 + (int) Offs; \
253 if (PCH != OldPCH) { \
263 unsigned Result = v1 - v2; \
264 TEST_ZF (Result & 0xFF); \
266 SET_CF (Result <= 0xFF); \
285 SET_CF (Val & 0x01); \
293 Warning ("Decimal mode not available"); \
296 unsigned char rhs = v; \
297 Val = AC - rhs - (!GET_CF ()); \
298 AC = (unsigned char) Val; \
301 SET_CF (Val <= 0xFF); \
302 SET_OF (((AC^rhs) & (AC^Val) & 0x80)); \
307 /*****************************************************************************/
308 /* Helper functions */
309 /*****************************************************************************/
313 static void OPC_Illegal (void)
315 Warning ("Illegal opcode $%02X at address $%04X\n", MemReadByte (PC), PC);
320 /*****************************************************************************/
322 /*****************************************************************************/
326 static void OPC_6502_00 (void)
327 /* Opcode $00: BRK */
336 PC = MemReadWord (0xFFFE);
342 static void OPC_6502_01 (void)
343 /* Opcode $01: ORA (ind,x) */
350 static void OPC_6502_05 (void)
351 /* Opcode $05: ORA zp */
358 static void OPC_6502_06 (void)
359 /* Opcode $06: ASL zp */
361 unsigned char ZPAddr;
364 ZPAddr = MemReadByte (PC+1);
365 Val = MemReadByte (ZPAddr) << 1;
366 MemWriteByte (ZPAddr, (unsigned char) Val);
367 TEST_ZF (Val & 0xFF);
369 SET_CF (Val & 0x100);
375 static void OPC_6502_08 (void)
376 /* Opcode $08: PHP */
385 static void OPC_6502_09 (void)
386 /* Opcode $09: ORA #imm */
393 static void OPC_6502_0A (void)
394 /* Opcode $0A: ASL a */
399 AC = (unsigned char) Val;
400 TEST_ZF (Val & 0xFF);
402 SET_CF (Val & 0x100);
408 static void OPC_6502_0D (void)
409 /* Opcode $0D: ORA abs */
416 static void OPC_6502_0E (void)
417 /* Opcode $0E: ALS abs */
422 Addr = MemReadWord (PC+1);
423 Val = MemReadByte (Addr) << 1;
424 MemWriteByte (Addr, (unsigned char) Val);
425 TEST_ZF (Val & 0xFF);
427 SET_CF (Val & 0x100);
433 static void OPC_6502_10 (void)
434 /* Opcode $10: BPL */
441 static void OPC_6502_11 (void)
442 /* Opcode $11: ORA (zp),y */
449 static void OPC_6502_15 (void)
450 /* Opcode $15: ORA zp,x */
457 static void OPC_6502_16 (void)
458 /* Opcode $16: ASL zp,x */
460 unsigned char ZPAddr;
463 ZPAddr = MemReadByte (PC+1) + XR;
464 Val = MemReadByte (ZPAddr) << 1;
465 MemWriteByte (ZPAddr, (unsigned char) Val);
466 TEST_ZF (Val & 0xFF);
468 SET_CF (Val & 0x100);
474 static void OPC_6502_18 (void)
475 /* Opcode $18: CLC */
484 static void OPC_6502_19 (void)
485 /* Opcode $19: ORA abs,y */
492 static void OPC_6502_1D (void)
493 /* Opcode $1D: ORA abs,x */
500 static void OPC_6502_1E (void)
501 /* Opcode $1E: ASL abs,x */
506 Addr = MemReadWord (PC+1) + XR;
507 Val = MemReadByte (Addr) << 1;
508 MemWriteByte (Addr, (unsigned char) Val);
509 TEST_ZF (Val & 0xFF);
511 SET_CF (Val & 0x100);
517 static void OPC_6502_20 (void)
518 /* Opcode $20: JSR */
522 Addr = MemReadWord (PC+1);
531 static void OPC_6502_21 (void)
532 /* Opcode $21: AND (zp,x) */
539 static void OPC_6502_24 (void)
540 /* Opcode $24: BIT zp */
542 unsigned char ZPAddr;
545 ZPAddr = MemReadByte (PC+1);
546 Val = MemReadByte (ZPAddr);
549 SET_ZF ((Val & AC) == 0);
555 static void OPC_6502_25 (void)
556 /* Opcode $25: AND zp */
563 static void OPC_6502_26 (void)
564 /* Opcode $26: ROL zp */
566 unsigned char ZPAddr;
569 ZPAddr = MemReadByte (PC+1);
570 Val = MemReadByte (ZPAddr);
572 MemWriteByte (ZPAddr, Val);
578 static void OPC_6502_28 (void)
579 /* Opcode $28: PLP */
588 static void OPC_6502_29 (void)
589 /* Opcode $29: AND #imm */
596 static void OPC_6502_2A (void)
597 /* Opcode $2A: ROL a */
603 AC = (unsigned char) Val;
609 static void OPC_6502_2C (void)
610 /* Opcode $2C: BIT abs */
615 Addr = MemReadByte (PC+1);
616 Val = MemReadByte (Addr);
619 SET_ZF ((Val & AC) == 0);
625 static void OPC_6502_2D (void)
626 /* Opcode $2D: AND abs */
633 static void OPC_6502_2E (void)
634 /* Opcode $2E: ROL abs */
639 Addr = MemReadWord (PC+1);
640 Val = MemReadByte (Addr);
642 MemWriteByte (Addr, Val);
648 static void OPC_6502_30 (void)
649 /* Opcode $30: BMI */
656 static void OPC_6502_31 (void)
657 /* Opcode $31: AND (zp),y */
664 static void OPC_6502_35 (void)
665 /* Opcode $35: AND zp,x */
672 static void OPC_6502_36 (void)
673 /* Opcode $36: ROL zp,x */
675 unsigned char ZPAddr;
678 ZPAddr = MemReadByte (PC+1) + XR;
679 Val = MemReadByte (ZPAddr);
681 MemWriteByte (ZPAddr, Val);
687 static void OPC_6502_38 (void)
688 /* Opcode $38: SEC */
697 static void OPC_6502_39 (void)
698 /* Opcode $39: AND abs,y */
705 static void OPC_6502_3D (void)
706 /* Opcode $3D: AND abs,x */
713 static void OPC_6502_3E (void)
714 /* Opcode $3E: ROL abs,x */
719 Addr = MemReadWord (PC+1) + XR;
720 Val = MemReadByte (Addr);
722 MemWriteByte (Addr, Val);
728 static void OPC_6502_40 (void)
729 /* Opcode $40: RTI */
733 PC = POP (); /* PCL */
734 PC |= (POP () << 8); /* PCH */
739 static void OPC_6502_41 (void)
740 /* Opcode $41: EOR (zp,x) */
747 static void OPC_6502_45 (void)
748 /* Opcode $45: EOR zp */
755 static void OPC_6502_46 (void)
756 /* Opcode $46: LSR zp */
758 unsigned char ZPAddr;
761 ZPAddr = MemReadByte (PC+1);
762 Val = MemReadByte (ZPAddr);
765 MemWriteByte (ZPAddr, Val);
773 static void OPC_6502_48 (void)
774 /* Opcode $48: PHA */
783 static void OPC_6502_49 (void)
784 /* Opcode $49: EOR #imm */
791 static void OPC_6502_4A (void)
792 /* Opcode $4A: LSR a */
804 static void OPC_6502_4C (void)
805 /* Opcode $4C: JMP abs */
808 PC = MemReadWord (PC+1);
813 static void OPC_6502_4D (void)
814 /* Opcode $4D: EOR abs */
821 static void OPC_6502_4E (void)
822 /* Opcode $4E: LSR abs */
827 Addr = MemReadWord (PC+1);
828 Val = MemReadByte (Addr);
831 MemWriteByte (Addr, Val);
839 static void OPC_6502_50 (void)
840 /* Opcode $50: BVC */
847 static void OPC_6502_51 (void)
848 /* Opcode $51: EOR (zp),y */
855 static void OPC_6502_55 (void)
856 /* Opcode $55: EOR zp,x */
863 static void OPC_6502_56 (void)
864 /* Opcode $56: LSR zp,x */
866 unsigned char ZPAddr;
869 ZPAddr = MemReadByte (PC+1) + XR;
870 Val = MemReadByte (ZPAddr);
873 MemWriteByte (ZPAddr, Val);
881 static void OPC_6502_58 (void)
882 /* Opcode $58: CLI */
891 static void OPC_6502_59 (void)
892 /* Opcode $59: EOR abs,y */
899 static void OPC_6502_5D (void)
900 /* Opcode $5D: EOR abs,x */
907 static void OPC_6502_5E (void)
908 /* Opcode $5E: LSR abs,x */
913 Addr = MemReadWord (PC+1) + XR;
914 Val = MemReadByte (Addr);
917 MemWriteByte (Addr, Val);
925 static void OPC_6502_60 (void)
926 /* Opcode $60: RTS */
929 PC = POP (); /* PCL */
930 PC |= (POP () << 8); /* PCH */
936 static void OPC_6502_61 (void)
937 /* Opcode $61: ADC (zp,x) */
939 unsigned char ZPAddr;
942 ZPAddr = MemReadByte (PC+1) + XR;
943 Addr = MemReadZPWord (ZPAddr);
944 ADC (MemReadByte (Addr));
950 static void OPC_6502_65 (void)
951 /* Opcode $65: ADC zp */
953 unsigned char ZPAddr;
955 ZPAddr = MemReadByte (PC+1);
956 ADC (MemReadByte (ZPAddr));
962 static void OPC_6502_66 (void)
963 /* Opcode $66: ROR zp */
965 unsigned char ZPAddr;
968 ZPAddr = MemReadByte (PC+1);
969 Val = MemReadByte (ZPAddr);
971 MemWriteByte (ZPAddr, Val);
977 static void OPC_6502_68 (void)
978 /* Opcode $68: PLA */
989 static void OPC_6502_69 (void)
990 /* Opcode $69: ADC #imm */
993 ADC (MemReadByte (PC+1));
999 static void OPC_6502_6A (void)
1000 /* Opcode $6A: ROR a */
1006 AC = (unsigned char) Val;
1012 static void OPC_6502_6C (void)
1013 /* Opcode $6C: JMP (ind) */
1017 Addr = MemReadWord (PC+1);
1018 if (CPU == CPU_6502) {
1019 /* Emulate the 6502 bug */
1020 PC = MemReadByte (Addr);
1021 Addr = (Addr & 0xFF00) | ((Addr + 1) & 0xFF);
1022 PC |= (MemReadByte (Addr) << 8);
1024 /* 65C02 and above have this bug fixed */
1025 PC = MemReadWord (Addr);
1031 static void OPC_6502_6D (void)
1032 /* Opcode $6D: ADC abs */
1036 Addr = MemReadWord (PC+1);
1037 ADC (MemReadByte (Addr));
1043 static void OPC_6502_6E (void)
1044 /* Opcode $6E: ROR abs */
1049 Addr = MemReadWord (PC+1);
1050 Val = MemReadByte (Addr);
1052 MemWriteByte (Addr, Val);
1058 static void OPC_6502_70 (void)
1059 /* Opcode $70: BVS */
1066 static void OPC_6502_71 (void)
1067 /* Opcode $71: ADC (zp),y */
1069 unsigned char ZPAddr;
1072 ZPAddr = MemReadByte (PC+1);
1073 Addr = MemReadZPWord (ZPAddr);
1074 if (PAGE_CROSS (Addr, YR)) {
1077 ADC (MemReadByte (Addr + YR));
1083 static void OPC_6502_75 (void)
1084 /* Opcode $75: ADC zp,x */
1086 unsigned char ZPAddr;
1088 ZPAddr = MemReadByte (PC+1) + XR;
1089 ADC (MemReadByte (ZPAddr));
1095 static void OPC_6502_76 (void)
1096 /* Opcode $76: ROR zp,x */
1098 unsigned char ZPAddr;
1101 ZPAddr = MemReadByte (PC+1) + XR;
1102 Val = MemReadByte (ZPAddr);
1104 MemWriteByte (ZPAddr, Val);
1110 static void OPC_6502_78 (void)
1111 /* Opcode $78: SEI */
1120 static void OPC_6502_79 (void)
1121 /* Opcode $79: ADC abs,y */
1125 Addr = MemReadWord (PC+1);
1126 if (PAGE_CROSS (Addr, YR)) {
1129 ADC (MemReadByte (Addr + YR));
1135 static void OPC_6502_7D (void)
1136 /* Opcode $7D: ADC abs,x */
1140 Addr = MemReadWord (PC+1);
1141 if (PAGE_CROSS (Addr, XR)) {
1144 ADC (MemReadByte (Addr + XR));
1150 static void OPC_6502_7E (void)
1151 /* Opcode $7E: ROR abs,x */
1156 Addr = MemReadByte (PC+1) + XR;
1157 Val = MemReadByte (Addr);
1159 MemWriteByte (Addr, Val);
1165 static void OPC_6502_81 (void)
1166 /* Opcode $81: STA (zp,x) */
1168 unsigned char ZPAddr;
1171 ZPAddr = MemReadByte (PC+1) + XR;
1172 Addr = MemReadZPWord (ZPAddr);
1173 MemWriteByte (Addr, AC);
1179 static void OPC_6502_84 (void)
1180 /* Opcode $84: STY zp */
1182 unsigned char ZPAddr;
1184 ZPAddr = MemReadByte (PC+1);
1185 MemWriteByte (ZPAddr, YR);
1191 static void OPC_6502_85 (void)
1192 /* Opcode $85: STA zp */
1194 unsigned char ZPAddr;
1196 ZPAddr = MemReadByte (PC+1);
1197 MemWriteByte (ZPAddr, AC);
1203 static void OPC_6502_86 (void)
1204 /* Opcode $86: STX zp */
1206 unsigned char ZPAddr;
1208 ZPAddr = MemReadByte (PC+1);
1209 MemWriteByte (ZPAddr, XR);
1215 static void OPC_6502_88 (void)
1216 /* Opcode $88: DEY */
1227 static void OPC_6502_8A (void)
1228 /* Opcode $8A: TXA */
1239 static void OPC_6502_8C (void)
1240 /* Opcode $8C: STY abs */
1244 Addr = MemReadWord (PC+1);
1245 MemWriteByte (Addr, YR);
1251 static void OPC_6502_8D (void)
1252 /* Opcode $8D: STA abs */
1256 Addr = MemReadWord (PC+1);
1257 MemWriteByte (Addr, AC);
1263 static void OPC_6502_8E (void)
1264 /* Opcode $8E: STX abs */
1268 Addr = MemReadWord (PC+1);
1269 MemWriteByte (Addr, XR);
1275 static void OPC_6502_90 (void)
1276 /* Opcode $90: BCC */
1278 BRANCH (!GET_CF ());
1283 static void OPC_6502_91 (void)
1284 /* Opcode $91: sta (zp),y */
1286 unsigned char ZPAddr;
1289 ZPAddr = MemReadByte (PC+1);
1290 Addr = MemReadZPWord (ZPAddr) + YR;
1291 MemWriteByte (Addr, AC);
1297 static void OPC_6502_94 (void)
1298 /* Opcode $94: STY zp,x */
1300 unsigned char ZPAddr;
1302 ZPAddr = MemReadByte (PC+1) + XR;
1303 MemWriteByte (ZPAddr, YR);
1309 static void OPC_6502_95 (void)
1310 /* Opcode $95: STA zp,x */
1312 unsigned char ZPAddr;
1314 ZPAddr = MemReadByte (PC+1) + XR;
1315 MemWriteByte (ZPAddr, AC);
1321 static void OPC_6502_96 (void)
1322 /* Opcode $96: stx zp,y */
1324 unsigned char ZPAddr;
1326 ZPAddr = MemReadByte (PC+1) + YR;
1327 MemWriteByte (ZPAddr, XR);
1333 static void OPC_6502_98 (void)
1334 /* Opcode $98: TYA */
1345 static void OPC_6502_99 (void)
1346 /* Opcode $99: STA abs,y */
1350 Addr = MemReadWord (PC+1) + YR;
1351 MemWriteByte (Addr, AC);
1357 static void OPC_6502_9A (void)
1358 /* Opcode $9A: TXS */
1367 static void OPC_6502_9D (void)
1368 /* Opcode $9D: STA abs,x */
1372 Addr = MemReadWord (PC+1) + XR;
1373 MemWriteByte (Addr, AC);
1379 static void OPC_6502_A0 (void)
1380 /* Opcode $A0: LDY #imm */
1383 YR = MemReadByte (PC+1);
1391 static void OPC_6502_A1 (void)
1392 /* Opcode $A1: LDA (zp,x) */
1394 unsigned char ZPAddr;
1397 ZPAddr = MemReadByte (PC+1) + XR;
1398 Addr = MemReadZPWord (ZPAddr);
1399 AC = MemReadByte (Addr);
1407 static void OPC_6502_A2 (void)
1408 /* Opcode $A2: LDX #imm */
1411 XR = MemReadByte (PC+1);
1419 static void OPC_6502_A4 (void)
1420 /* Opcode $A4: LDY zp */
1422 unsigned char ZPAddr;
1424 ZPAddr = MemReadByte (PC+1);
1425 YR = MemReadByte (ZPAddr);
1433 static void OPC_6502_A5 (void)
1434 /* Opcode $A5: LDA zp */
1436 unsigned char ZPAddr;
1438 ZPAddr = MemReadByte (PC+1);
1439 AC = MemReadByte (ZPAddr);
1447 static void OPC_6502_A6 (void)
1448 /* Opcode $A6: LDX zp */
1450 unsigned char ZPAddr;
1452 ZPAddr = MemReadByte (PC+1);
1453 XR = MemReadByte (ZPAddr);
1461 static void OPC_6502_A8 (void)
1462 /* Opcode $A8: TAY */
1473 static void OPC_6502_A9 (void)
1474 /* Opcode $A9: LDA #imm */
1477 AC = MemReadByte (PC+1);
1485 static void OPC_6502_AA (void)
1486 /* Opcode $AA: TAX */
1497 static void OPC_6502_AC (void)
1498 /* Opcode $AC: LDY abs */
1502 Addr = MemReadWord (PC+1);
1503 YR = MemReadByte (Addr);
1511 static void OPC_6502_AD (void)
1512 /* Opcode $AD: LDA abs */
1516 Addr = MemReadWord (PC+1);
1517 AC = MemReadByte (Addr);
1525 static void OPC_6502_AE (void)
1526 /* Opcode $AE: LDX abs */
1530 Addr = MemReadWord (PC+1);
1531 XR = MemReadByte (Addr);
1539 static void OPC_6502_B0 (void)
1540 /* Opcode $B0: BCS */
1547 static void OPC_6502_B1 (void)
1548 /* Opcode $B1: LDA (zp),y */
1550 unsigned char ZPAddr;
1553 ZPAddr = MemReadByte (PC+1);
1554 Addr = MemReadZPWord (ZPAddr);
1555 if (PAGE_CROSS (Addr, YR)) {
1558 AC = MemReadByte (Addr + YR);
1566 static void OPC_6502_B4 (void)
1567 /* Opcode $B4: LDY zp,x */
1569 unsigned char ZPAddr;
1571 ZPAddr = MemReadByte (PC+1) + XR;
1572 YR = MemReadByte (ZPAddr);
1580 static void OPC_6502_B5 (void)
1581 /* Opcode $B5: LDA zp,x */
1583 unsigned char ZPAddr;
1585 ZPAddr = MemReadByte (PC+1) + XR;
1586 AC = MemReadByte (ZPAddr);
1594 static void OPC_6502_B6 (void)
1595 /* Opcode $B6: LDX zp,y */
1597 unsigned char ZPAddr;
1599 ZPAddr = MemReadByte (PC+1) + YR;
1600 XR = MemReadByte (ZPAddr);
1608 static void OPC_6502_B8 (void)
1609 /* Opcode $B8: CLV */
1618 static void OPC_6502_B9 (void)
1619 /* Opcode $B9: LDA abs,y */
1623 Addr = MemReadWord (PC+1);
1624 if (PAGE_CROSS (Addr, YR)) {
1627 AC = MemReadByte (Addr + YR);
1635 static void OPC_6502_BA (void)
1636 /* Opcode $BA: TSX */
1647 static void OPC_6502_BC (void)
1648 /* Opcode $BC: LDY abs,x */
1652 Addr = MemReadWord (PC+1);
1653 if (PAGE_CROSS (Addr, XR)) {
1656 YR = MemReadByte (Addr + XR);
1664 static void OPC_6502_BD (void)
1665 /* Opcode $BD: LDA abs,x */
1669 Addr = MemReadWord (PC+1);
1670 if (PAGE_CROSS (Addr, XR)) {
1673 AC = MemReadByte (Addr + XR);
1681 static void OPC_6502_BE (void)
1682 /* Opcode $BE: LDX abs,y */
1686 Addr = MemReadWord (PC+1);
1687 if (PAGE_CROSS (Addr, YR)) {
1690 XR = MemReadByte (Addr + YR);
1698 static void OPC_6502_C0 (void)
1699 /* Opcode $C0: CPY #imm */
1702 CMP (YR, MemReadByte (PC+1));
1708 static void OPC_6502_C1 (void)
1709 /* Opcode $C1: CMP (zp,x) */
1711 unsigned char ZPAddr;
1714 ZPAddr = MemReadByte (PC+1) + XR;
1715 Addr = MemReadZPWord (ZPAddr);
1716 CMP (AC, MemReadByte (Addr));
1722 static void OPC_6502_C4 (void)
1723 /* Opcode $C4: CPY zp */
1725 unsigned char ZPAddr;
1727 ZPAddr = MemReadByte (PC+1);
1728 CMP (YR, MemReadByte (ZPAddr));
1734 static void OPC_6502_C5 (void)
1735 /* Opcode $C5: CMP zp */
1737 unsigned char ZPAddr;
1739 ZPAddr = MemReadByte (PC+1);
1740 CMP (AC, MemReadByte (ZPAddr));
1746 static void OPC_6502_C6 (void)
1747 /* Opcode $C6: DEC zp */
1749 unsigned char ZPAddr;
1752 ZPAddr = MemReadByte (PC+1);
1753 Val = MemReadByte (ZPAddr) - 1;
1754 MemWriteByte (ZPAddr, Val);
1762 static void OPC_6502_C8 (void)
1763 /* Opcode $C8: INY */
1774 static void OPC_6502_C9 (void)
1775 /* Opcode $C9: CMP #imm */
1778 CMP (AC, MemReadByte (PC+1));
1784 static void OPC_6502_CA (void)
1785 /* Opcode $CA: DEX */
1796 static void OPC_6502_CC (void)
1797 /* Opcode $CC: CPY abs */
1801 Addr = MemReadWord (PC+1);
1802 CMP (YR, MemReadByte (Addr));
1808 static void OPC_6502_CD (void)
1809 /* Opcode $CD: CMP abs */
1813 Addr = MemReadWord (PC+1);
1814 CMP (AC, MemReadByte (Addr));
1820 static void OPC_6502_CE (void)
1821 /* Opcode $CE: DEC abs */
1826 Addr = MemReadWord (PC+1);
1827 Val = MemReadByte (Addr) - 1;
1828 MemWriteByte (Addr, Val);
1836 static void OPC_6502_D0 (void)
1837 /* Opcode $D0: BNE */
1839 BRANCH (!GET_ZF ());
1844 static void OPC_6502_D1 (void)
1845 /* Opcode $D1: CMP (zp),y */
1850 ZPAddr = MemReadByte (PC+1);
1851 Addr = MemReadWord (ZPAddr);
1852 if (PAGE_CROSS (Addr, YR)) {
1855 CMP (AC, MemReadByte (Addr + YR));
1861 static void OPC_6502_D5 (void)
1862 /* Opcode $D5: CMP zp,x */
1864 unsigned char ZPAddr;
1866 ZPAddr = MemReadByte (PC+1) + XR;
1867 CMP (AC, MemReadByte (ZPAddr));
1873 static void OPC_6502_D6 (void)
1874 /* Opcode $D6: DEC zp,x */
1876 unsigned char ZPAddr;
1879 ZPAddr = MemReadByte (PC+1) + XR;
1880 Val = MemReadByte (ZPAddr) - 1;
1881 MemWriteByte (ZPAddr, Val);
1889 static void OPC_6502_D8 (void)
1890 /* Opcode $D8: CLD */
1899 static void OPC_6502_D9 (void)
1900 /* Opcode $D9: CMP abs,y */
1904 Addr = MemReadWord (PC+1);
1905 if (PAGE_CROSS (Addr, YR)) {
1908 CMP (AC, MemReadByte (Addr + YR));
1914 static void OPC_6502_DD (void)
1915 /* Opcode $DD: CMP abs,x */
1919 Addr = MemReadWord (PC+1);
1920 if (PAGE_CROSS (Addr, XR)) {
1923 CMP (AC, MemReadByte (Addr + XR));
1929 static void OPC_6502_DE (void)
1930 /* Opcode $DE: DEC abs,x */
1935 Addr = MemReadWord (PC+1) + XR;
1936 Val = MemReadByte (Addr) - 1;
1937 MemWriteByte (Addr, Val);
1945 static void OPC_6502_E0 (void)
1946 /* Opcode $E0: CPX #imm */
1949 CMP (XR, MemReadByte (PC+1));
1955 static void OPC_6502_E1 (void)
1956 /* Opcode $E1: SBC (zp,x) */
1958 unsigned char ZPAddr;
1961 ZPAddr = MemReadByte (PC+1) + XR;
1962 Addr = MemReadZPWord (ZPAddr);
1963 SBC (MemReadByte (Addr));
1969 static void OPC_6502_E4 (void)
1970 /* Opcode $E4: CPX zp */
1972 unsigned char ZPAddr;
1974 ZPAddr = MemReadByte (PC+1);
1975 CMP (XR, MemReadByte (ZPAddr));
1981 static void OPC_6502_E5 (void)
1982 /* Opcode $E5: SBC zp */
1984 unsigned char ZPAddr;
1986 ZPAddr = MemReadByte (PC+1);
1987 SBC (MemReadByte (ZPAddr));
1993 static void OPC_6502_E6 (void)
1994 /* Opcode $E6: INC zp */
1996 unsigned char ZPAddr;
1999 ZPAddr = MemReadByte (PC+1);
2000 Val = MemReadByte (ZPAddr) + 1;
2001 MemWriteByte (ZPAddr, Val);
2009 static void OPC_6502_E8 (void)
2010 /* Opcode $E8: INX */
2021 static void OPC_6502_E9 (void)
2022 /* Opcode $E9: SBC #imm */
2025 SBC (MemReadByte (PC+1));
2031 static void OPC_6502_EA (void)
2032 /* Opcode $EA: NOP */
2034 /* This one is easy... */
2041 static void OPC_6502_EC (void)
2042 /* Opcode $EC: CPX abs */
2046 Addr = MemReadWord (PC+1);
2047 CMP (XR, MemReadByte (Addr));
2053 static void OPC_6502_ED (void)
2054 /* Opcode $ED: SBC abs */
2058 Addr = MemReadWord (PC+1);
2059 SBC (MemReadByte (Addr));
2065 static void OPC_6502_EE (void)
2066 /* Opcode $EE: INC abs */
2071 Addr = MemReadWord (PC+1);
2072 Val = MemReadByte (Addr) + 1;
2073 MemWriteByte (Addr, Val);
2081 static void OPC_6502_F0 (void)
2082 /* Opcode $F0: BEQ */
2089 static void OPC_6502_F1 (void)
2090 /* Opcode $F1: SBC (zp),y */
2092 unsigned char ZPAddr;
2095 ZPAddr = MemReadByte (PC+1);
2096 Addr = MemReadZPWord (ZPAddr);
2097 if (PAGE_CROSS (Addr, YR)) {
2100 SBC (MemReadByte (Addr + YR));
2106 static void OPC_6502_F5 (void)
2107 /* Opcode $F5: SBC zp,x */
2109 unsigned char ZPAddr;
2111 ZPAddr = MemReadByte (PC+1) + XR;
2112 SBC (MemReadByte (ZPAddr));
2118 static void OPC_6502_F6 (void)
2119 /* Opcode $F6: INC zp,x */
2121 unsigned char ZPAddr;
2124 ZPAddr = MemReadByte (PC+1) + XR;
2125 Val = MemReadByte (ZPAddr) + 1;
2126 MemWriteByte (ZPAddr, Val);
2134 static void OPC_6502_F8 (void)
2135 /* Opcode $F8: SED */
2142 static void OPC_6502_F9 (void)
2143 /* Opcode $F9: SBC abs,y */
2147 Addr = MemReadWord (PC+1);
2148 if (PAGE_CROSS (Addr, YR)) {
2151 SBC (MemReadByte (Addr + YR));
2157 static void OPC_6502_FD (void)
2158 /* Opcode $FD: SBC abs,x */
2162 Addr = MemReadWord (PC+1);
2163 if (PAGE_CROSS (Addr, XR)) {
2166 SBC (MemReadByte (Addr + XR));
2172 static void OPC_6502_FE (void)
2173 /* Opcode $FE: INC abs,x */
2178 Addr = MemReadWord (PC+1) + XR;
2179 Val = MemReadByte (Addr) + 1;
2180 MemWriteByte (Addr, Val);
2188 /*****************************************************************************/
2190 /*****************************************************************************/
2194 /* Opcode handler table */
2195 typedef void (*OPCFunc) (void);
2196 static OPCFunc OPCTable[256] = {
2457 /*****************************************************************************/
2459 /*****************************************************************************/
2464 /* Initialize the CPU */
2466 PC = MemReadWord (0xFFFC);
2479 /* Generate an IRQ */
2486 /* Generate an NMI */
2495 while (!CPUHalted) {
2497 /* Get the next opcode */
2498 unsigned char OPC = MemReadByte (PC);
2500 printf ("%6lu %04X %02X A=%02X X=%02X Y=%02X %c%c%c%c%c%c%c\n",
2501 TotalCycles, PC, OPC, AC, XR, YR,
2502 GET_SF()? 'S' : '-',
2503 GET_ZF()? 'Z' : '-',
2504 GET_CF()? 'C' : '-',
2505 GET_IF()? 'I' : '-',
2506 GET_BF()? 'B' : '-',
2507 GET_DF()? 'D' : '-',
2508 GET_OF()? 'V' : '-');
2514 TotalCycles += Cycles;