1 /*****************************************************************************/
5 /* CPU core for the 6502 */
9 /* (C) 2003-2012, Ullrich von Bassewitz */
10 /* Roemerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
14 /* Mar-2017, Christian Krueger, added support for 65SC02 */
16 /* This software is provided 'as-is', without any expressed or implied */
17 /* warranty. In no event will the authors be held liable for any damages */
18 /* arising from the use of this software. */
20 /* Permission is granted to anyone to use this software for any purpose, */
21 /* including commercial applications, and to alter it and redistribute it */
22 /* freely, subject to the following restrictions: */
24 /* 1. The origin of this software must not be misrepresented; you must not */
25 /* claim that you wrote the original software. If you use this software */
26 /* in a product, an acknowledgment in the product documentation would be */
27 /* appreciated but is not required. */
28 /* 2. Altered source versions must be plainly marked as such, and must not */
29 /* be misrepresented as being the original software. */
30 /* 3. This notice may not be removed or altered from any source */
33 /*****************************************************************************/
35 /* Known bugs and limitations of the 65C02 simulation:
36 * support currently only on the level of 65SC02:
37 BBRx, BBSx, RMBx, SMBx, WAI, and STP are unsupported
38 * BCD flag handling equals 6502 (unchecked if bug is simulated or wrong for
49 /*****************************************************************************/
51 /*****************************************************************************/
58 /* Type of an opcode handler function */
59 typedef void (*OPFunc) (void);
61 /* The CPU registers */
64 /* Cycles for the current insn */
65 static unsigned Cycles;
67 /* Total number of CPU cycles exec'd */
68 static unsigned long TotalCycles;
70 /* NMI request active */
71 static unsigned HaveNMIRequest;
73 /* IRQ request active */
74 static unsigned HaveIRQRequest;
76 /* flag to print cycles at program termination */
80 /*****************************************************************************/
81 /* Helper functions and macros */
82 /*****************************************************************************/
86 /* Return the flags as boolean values (0/1) */
87 #define GET_CF() ((Regs.SR & CF) != 0)
88 #define GET_ZF() ((Regs.SR & ZF) != 0)
89 #define GET_IF() ((Regs.SR & IF) != 0)
90 #define GET_DF() ((Regs.SR & DF) != 0)
91 #define GET_OF() ((Regs.SR & OF) != 0)
92 #define GET_SF() ((Regs.SR & SF) != 0)
94 /* Set the flags. The parameter is a boolean flag that says if the flag should be
97 #define SET_CF(f) do { if (f) { Regs.SR |= CF; } else { Regs.SR &= ~CF; } } while (0)
98 #define SET_ZF(f) do { if (f) { Regs.SR |= ZF; } else { Regs.SR &= ~ZF; } } while (0)
99 #define SET_IF(f) do { if (f) { Regs.SR |= IF; } else { Regs.SR &= ~IF; } } while (0)
100 #define SET_DF(f) do { if (f) { Regs.SR |= DF; } else { Regs.SR &= ~DF; } } while (0)
101 #define SET_OF(f) do { if (f) { Regs.SR |= OF; } else { Regs.SR &= ~OF; } } while (0)
102 #define SET_SF(f) do { if (f) { Regs.SR |= SF; } else { Regs.SR &= ~SF; } } while (0)
104 /* Special test and set macros. The meaning of the parameter depends on the
105 ** actual flag that should be set or reset.
107 #define TEST_ZF(v) SET_ZF (((v) & 0xFF) == 0)
108 #define TEST_SF(v) SET_SF (((v) & 0x80) != 0)
109 #define TEST_CF(v) SET_CF (((v) & 0xFF00) != 0)
111 /* Program counter halves */
112 #define PCL (Regs.PC & 0xFF)
113 #define PCH ((Regs.PC >> 8) & 0xFF)
115 /* Stack operations */
116 #define PUSH(Val) MemWriteByte (0x0100 | (Regs.SP-- & 0xFF), Val)
117 #define POP() MemReadByte (0x0100 | (++Regs.SP & 0xFF))
119 /* Test for page cross */
120 #define PAGE_CROSS(addr,offs) ((((addr) & 0xFF) + offs) >= 0x100)
123 #define AC_OP_IMM(op) \
125 Regs.AC = Regs.AC op MemReadByte (Regs.PC+1); \
131 #define AC_OP_ZP(op) \
133 Regs.AC = Regs.AC op MemReadByte (MemReadByte (Regs.PC+1)); \
139 #define AC_OP_ZPX(op) \
140 unsigned char ZPAddr; \
142 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; \
143 Regs.AC = Regs.AC op MemReadByte (ZPAddr); \
149 #define AC_OP_ZPY(op) \
150 unsigned char ZPAddr; \
152 ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR; \
153 Regs.AC = Regs.AC op MemReadByte (ZPAddr); \
159 #define AC_OP_ABS(op) \
162 Addr = MemReadWord (Regs.PC+1); \
163 Regs.AC = Regs.AC op MemReadByte (Addr); \
169 #define AC_OP_ABSX(op) \
172 Addr = MemReadWord (Regs.PC+1); \
173 if (PAGE_CROSS (Addr, Regs.XR)) { \
176 Regs.AC = Regs.AC op MemReadByte (Addr + Regs.XR); \
182 #define AC_OP_ABSY(op) \
185 Addr = MemReadWord (Regs.PC+1); \
186 if (PAGE_CROSS (Addr, Regs.YR)) { \
189 Regs.AC = Regs.AC op MemReadByte (Addr + Regs.YR); \
195 #define AC_OP_ZPXIND(op) \
196 unsigned char ZPAddr; \
199 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; \
200 Addr = MemReadZPWord (ZPAddr); \
201 Regs.AC = Regs.AC op MemReadByte (Addr); \
207 #define AC_OP_ZPINDY(op) \
208 unsigned char ZPAddr; \
211 ZPAddr = MemReadByte (Regs.PC+1); \
212 Addr = MemReadZPWord (ZPAddr); \
213 if (PAGE_CROSS (Addr, Regs.YR)) { \
217 Regs.AC = Regs.AC op MemReadByte (Addr); \
223 #define AC_OP_ZPIND(op) \
224 unsigned char ZPAddr; \
227 ZPAddr = MemReadByte (Regs.PC+1); \
228 Addr = MemReadZPWord (ZPAddr); \
229 Regs.AC = Regs.AC op MemReadByte (Addr); \
237 unsigned old = Regs.AC; \
238 unsigned rhs = (v & 0xFF); \
242 lo = (old & 0x0F) + (rhs & 0x0F) + GET_CF (); \
244 lo = ((lo + 0x06) & 0x0F) + 0x10; \
246 Regs.AC = (old & 0xF0) + (rhs & 0xF0) + lo; \
247 res = (signed char)(old & 0xF0) + \
248 (signed char)(rhs & 0xF0) + \
250 TEST_ZF (old + rhs + GET_CF ()); \
252 if (Regs.AC >= 0xA0) { \
256 SET_OF ((res < -128) || (res > 127)); \
257 if (CPU != CPU_6502) { \
261 Regs.AC += rhs + GET_CF (); \
265 SET_OF (!((old ^ rhs) & 0x80) && \
266 ((old ^ Regs.AC) & 0x80)); \
272 #define BRANCH(cond) \
276 unsigned char OldPCH; \
278 Offs = (signed char) MemReadByte (Regs.PC+1); \
280 Regs.PC += 2 + (int) Offs; \
281 if (PCH != OldPCH) { \
289 #define CMP(v1, v2) \
291 unsigned Result = v1 - v2; \
292 TEST_ZF (Result & 0xFF); \
294 SET_CF (Result <= 0xFF); \
313 SET_CF (Val & 0x01); \
321 unsigned old = Regs.AC; \
322 unsigned rhs = (v & 0xFF); \
326 lo = (old & 0x0F) - (rhs & 0x0F) + GET_CF () - 1; \
328 lo = ((lo - 0x06) & 0x0F) - 0x10; \
330 Regs.AC = (old & 0xF0) - (rhs & 0xF0) + lo; \
331 if (Regs.AC & 0x80) { \
334 res = Regs.AC - rhs + (!GET_CF ()); \
337 SET_CF (res <= 0xFF); \
338 SET_OF (((old^rhs) & (old^res) & 0x80)); \
339 if (CPU != CPU_6502) { \
343 Regs.AC -= rhs + (!GET_CF ()); \
346 SET_CF (Regs.AC <= 0xFF); \
347 SET_OF (((old^rhs) & (old^Regs.AC) & 0x80)); \
354 /*****************************************************************************/
355 /* Opcode handling functions */
356 /*****************************************************************************/
360 static void OPC_Illegal (void)
362 Error ("Illegal opcode $%02X at address $%04X",
363 MemReadByte (Regs.PC), Regs.PC);
368 static void OPC_6502_00 (void)
369 /* Opcode $00: BRK */
381 Regs.PC = MemReadWord (0xFFFE);
386 static void OPC_6502_01 (void)
387 /* Opcode $01: ORA (ind,x) */
394 static void OPC_65SC02_04 (void)
395 /* Opcode $04: TSB zp */
397 unsigned char ZPAddr;
400 ZPAddr = MemReadByte (Regs.PC+1);
401 Val = MemReadByte (ZPAddr);
402 SET_ZF ((Val & Regs.AC) == 0);
403 MemWriteByte (ZPAddr, (unsigned char)(Val | Regs.AC));
409 static void OPC_6502_05 (void)
410 /* Opcode $05: ORA zp */
417 static void OPC_6502_06 (void)
418 /* Opcode $06: ASL zp */
420 unsigned char ZPAddr;
423 ZPAddr = MemReadByte (Regs.PC+1);
424 Val = MemReadByte (ZPAddr) << 1;
425 MemWriteByte (ZPAddr, (unsigned char) Val);
426 TEST_ZF (Val & 0xFF);
428 SET_CF (Val & 0x100);
434 static void OPC_6502_08 (void)
435 /* Opcode $08: PHP */
444 static void OPC_6502_09 (void)
445 /* Opcode $09: ORA #imm */
452 static void OPC_6502_0A (void)
453 /* Opcode $0A: ASL a */
457 TEST_ZF (Regs.AC & 0xFF);
459 SET_CF (Regs.AC & 0x100);
466 static void OPC_65SC02_0C (void)
467 /* Opcode $0C: TSB abs */
472 Addr = MemReadWord (Regs.PC+1);
473 Val = MemReadByte (Addr);
474 SET_ZF ((Val & Regs.AC) == 0);
475 MemWriteByte (Addr, (unsigned char) (Val | Regs.AC));
481 static void OPC_6502_0D (void)
482 /* Opcode $0D: ORA abs */
489 static void OPC_6502_0E (void)
490 /* Opcode $0E: ALS abs */
495 Addr = MemReadWord (Regs.PC+1);
496 Val = MemReadByte (Addr) << 1;
497 MemWriteByte (Addr, (unsigned char) Val);
498 TEST_ZF (Val & 0xFF);
500 SET_CF (Val & 0x100);
506 static void OPC_6502_10 (void)
507 /* Opcode $10: BPL */
514 static void OPC_6502_11 (void)
515 /* Opcode $11: ORA (zp),y */
522 static void OPC_65SC02_12 (void)
523 /* Opcode $12: ORA (zp) */
530 static void OPC_65SC02_14 (void)
531 /* Opcode $14: TRB zp */
533 unsigned char ZPAddr;
536 ZPAddr = MemReadByte (Regs.PC+1);
537 Val = MemReadByte (ZPAddr);
538 SET_ZF ((Val & Regs.AC) == 0);
539 MemWriteByte (ZPAddr, (unsigned char)(Val & ~Regs.AC));
545 static void OPC_6502_15 (void)
546 /* Opcode $15: ORA zp,x */
553 static void OPC_6502_16 (void)
554 /* Opcode $16: ASL zp,x */
556 unsigned char ZPAddr;
559 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
560 Val = MemReadByte (ZPAddr) << 1;
561 MemWriteByte (ZPAddr, (unsigned char) Val);
562 TEST_ZF (Val & 0xFF);
564 SET_CF (Val & 0x100);
570 static void OPC_6502_18 (void)
571 /* Opcode $18: CLC */
580 static void OPC_6502_19 (void)
581 /* Opcode $19: ORA abs,y */
588 static void OPC_65SC02_1A (void)
589 /* Opcode $1A: INC a */
592 Regs.AC = (Regs.AC + 1) & 0xFF;
600 static void OPC_65SC02_1C (void)
601 /* Opcode $1C: TRB abs */
606 Addr = MemReadWord (Regs.PC+1);
607 Val = MemReadByte (Addr);
608 SET_ZF ((Val & Regs.AC) == 0);
609 MemWriteByte (Addr, (unsigned char) (Val & ~Regs.AC));
615 static void OPC_6502_1D (void)
616 /* Opcode $1D: ORA abs,x */
623 static void OPC_6502_1E (void)
624 /* Opcode $1E: ASL abs,x */
629 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
630 if (CPU != CPU_6502 && !PAGE_CROSS (Addr, Regs.XR))
632 Val = MemReadByte (Addr) << 1;
633 MemWriteByte (Addr, (unsigned char) Val);
634 TEST_ZF (Val & 0xFF);
636 SET_CF (Val & 0x100);
642 static void OPC_6502_20 (void)
643 /* Opcode $20: JSR */
647 Addr = MemReadWord (Regs.PC+1);
653 ParaVirtHooks (&Regs);
658 static void OPC_6502_21 (void)
659 /* Opcode $21: AND (zp,x) */
666 static void OPC_6502_24 (void)
667 /* Opcode $24: BIT zp */
669 unsigned char ZPAddr;
672 ZPAddr = MemReadByte (Regs.PC+1);
673 Val = MemReadByte (ZPAddr);
676 SET_ZF ((Val & Regs.AC) == 0);
682 static void OPC_6502_25 (void)
683 /* Opcode $25: AND zp */
690 static void OPC_6502_26 (void)
691 /* Opcode $26: ROL zp */
693 unsigned char ZPAddr;
696 ZPAddr = MemReadByte (Regs.PC+1);
697 Val = MemReadByte (ZPAddr);
699 MemWriteByte (ZPAddr, Val);
705 static void OPC_6502_28 (void)
706 /* Opcode $28: PLP */
710 /* Bits 5 and 4 aren't used, and always are 1! */
711 Regs.SR = (POP () | 0x30);
717 static void OPC_6502_29 (void)
718 /* Opcode $29: AND #imm */
725 static void OPC_6502_2A (void)
726 /* Opcode $2A: ROL a */
736 static void OPC_6502_2C (void)
737 /* Opcode $2C: BIT abs */
742 Addr = MemReadWord (Regs.PC+1);
743 Val = MemReadByte (Addr);
746 SET_ZF ((Val & Regs.AC) == 0);
752 static void OPC_6502_2D (void)
753 /* Opcode $2D: AND abs */
760 static void OPC_6502_2E (void)
761 /* Opcode $2E: ROL abs */
766 Addr = MemReadWord (Regs.PC+1);
767 Val = MemReadByte (Addr);
769 MemWriteByte (Addr, Val);
775 static void OPC_6502_30 (void)
776 /* Opcode $30: BMI */
783 static void OPC_6502_31 (void)
784 /* Opcode $31: AND (zp),y */
791 static void OPC_65SC02_32 (void)
792 /* Opcode $32: AND (zp) */
799 static void OPC_65SC02_34 (void)
800 /* Opcode $34: BIT zp,x */
802 unsigned char ZPAddr;
805 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
806 Val = MemReadByte (ZPAddr);
809 SET_ZF ((Val & Regs.AC) == 0);
815 static void OPC_6502_35 (void)
816 /* Opcode $35: AND zp,x */
823 static void OPC_6502_36 (void)
824 /* Opcode $36: ROL zp,x */
826 unsigned char ZPAddr;
829 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
830 Val = MemReadByte (ZPAddr);
832 MemWriteByte (ZPAddr, Val);
838 static void OPC_6502_38 (void)
839 /* Opcode $38: SEC */
848 static void OPC_6502_39 (void)
849 /* Opcode $39: AND abs,y */
856 static void OPC_65SC02_3A (void)
857 /* Opcode $3A: DEC a */
860 Regs.AC = (Regs.AC - 1) & 0xFF;
868 static void OPC_65SC02_3C (void)
869 /* Opcode $3C: BIT abs,x */
874 Addr = MemReadWord (Regs.PC+1);
875 if (PAGE_CROSS (Addr, Regs.XR))
877 Val = MemReadByte (Addr + Regs.XR);
880 SET_ZF ((Val & Regs.AC) == 0);
886 static void OPC_6502_3D (void)
887 /* Opcode $3D: AND abs,x */
894 static void OPC_6502_3E (void)
895 /* Opcode $3E: ROL abs,x */
900 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
901 if (CPU != CPU_6502 && !PAGE_CROSS (Addr, Regs.XR))
903 Val = MemReadByte (Addr);
905 MemWriteByte (Addr, Val);
911 static void OPC_6502_40 (void)
912 /* Opcode $40: RTI */
916 /* Bits 5 and 4 aren't used, and always are 1! */
917 Regs.SR = POP () | 0x30;
918 Regs.PC = POP (); /* PCL */
919 Regs.PC |= (POP () << 8); /* PCH */
924 static void OPC_6502_41 (void)
925 /* Opcode $41: EOR (zp,x) */
932 static void OPC_65C02_44 (void)
933 /* Opcode $44: 'zp' 3 cycle NOP */
941 static void OPC_6502_45 (void)
942 /* Opcode $45: EOR zp */
949 static void OPC_6502_46 (void)
950 /* Opcode $46: LSR zp */
952 unsigned char ZPAddr;
955 ZPAddr = MemReadByte (Regs.PC+1);
956 Val = MemReadByte (ZPAddr);
959 MemWriteByte (ZPAddr, Val);
967 static void OPC_6502_48 (void)
968 /* Opcode $48: PHA */
977 static void OPC_6502_49 (void)
978 /* Opcode $49: EOR #imm */
985 static void OPC_6502_4A (void)
986 /* Opcode $4A: LSR a */
989 SET_CF (Regs.AC & 0x01);
998 static void OPC_6502_4C (void)
999 /* Opcode $4C: JMP abs */
1002 Regs.PC = MemReadWord (Regs.PC+1);
1004 ParaVirtHooks (&Regs);
1009 static void OPC_6502_4D (void)
1010 /* Opcode $4D: EOR abs */
1017 static void OPC_6502_4E (void)
1018 /* Opcode $4E: LSR abs */
1023 Addr = MemReadWord (Regs.PC+1);
1024 Val = MemReadByte (Addr);
1025 SET_CF (Val & 0x01);
1027 MemWriteByte (Addr, Val);
1035 static void OPC_6502_50 (void)
1036 /* Opcode $50: BVC */
1038 BRANCH (!GET_OF ());
1043 static void OPC_6502_51 (void)
1044 /* Opcode $51: EOR (zp),y */
1051 static void OPC_65SC02_52 (void)
1052 /* Opcode $52: EOR (zp) */
1059 static void OPC_6502_55 (void)
1060 /* Opcode $55: EOR zp,x */
1067 static void OPC_6502_56 (void)
1068 /* Opcode $56: LSR zp,x */
1070 unsigned char ZPAddr;
1073 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1074 Val = MemReadByte (ZPAddr);
1075 SET_CF (Val & 0x01);
1077 MemWriteByte (ZPAddr, Val);
1085 static void OPC_6502_58 (void)
1086 /* Opcode $58: CLI */
1095 static void OPC_6502_59 (void)
1096 /* Opcode $59: EOR abs,y */
1103 static void OPC_65SC02_5A (void)
1104 /* Opcode $5A: PHY */
1113 static void OPC_65C02_5C (void)
1114 /* Opcode $5C: 'Absolute' 8 cycle NOP */
1122 static void OPC_6502_5D (void)
1123 /* Opcode $5D: EOR abs,x */
1130 static void OPC_6502_5E (void)
1131 /* Opcode $5E: LSR abs,x */
1136 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
1137 if (CPU != CPU_6502 && !PAGE_CROSS (Addr, Regs.XR))
1139 Val = MemReadByte (Addr);
1140 SET_CF (Val & 0x01);
1142 MemWriteByte (Addr, Val);
1150 static void OPC_6502_60 (void)
1151 /* Opcode $60: RTS */
1154 Regs.PC = POP (); /* PCL */
1155 Regs.PC |= (POP () << 8); /* PCH */
1161 static void OPC_6502_61 (void)
1162 /* Opcode $61: ADC (zp,x) */
1164 unsigned char ZPAddr;
1167 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1168 Addr = MemReadZPWord (ZPAddr);
1169 ADC (MemReadByte (Addr));
1175 static void OPC_65SC02_64 (void)
1176 /* Opcode $64: STZ zp */
1178 unsigned char ZPAddr;
1180 ZPAddr = MemReadByte (Regs.PC+1);
1181 MemWriteByte (ZPAddr, 0);
1187 static void OPC_6502_65 (void)
1188 /* Opcode $65: ADC zp */
1190 unsigned char ZPAddr;
1192 ZPAddr = MemReadByte (Regs.PC+1);
1193 ADC (MemReadByte (ZPAddr));
1199 static void OPC_6502_66 (void)
1200 /* Opcode $66: ROR zp */
1202 unsigned char ZPAddr;
1205 ZPAddr = MemReadByte (Regs.PC+1);
1206 Val = MemReadByte (ZPAddr);
1208 MemWriteByte (ZPAddr, Val);
1214 static void OPC_6502_68 (void)
1215 /* Opcode $68: PLA */
1226 static void OPC_6502_69 (void)
1227 /* Opcode $69: ADC #imm */
1230 ADC (MemReadByte (Regs.PC+1));
1236 static void OPC_6502_6A (void)
1237 /* Opcode $6A: ROR a */
1246 static void OPC_6502_6C (void)
1247 /* Opcode $6C: JMP (ind) */
1249 unsigned PC, Lo, Hi;
1251 Lo = MemReadWord (PC+1);
1253 if (CPU == CPU_6502)
1255 /* Emulate the 6502 bug */
1257 Regs.PC = MemReadByte (Lo);
1258 Hi = (Lo & 0xFF00) | ((Lo + 1) & 0xFF);
1259 Regs.PC |= (MemReadByte (Hi) << 8);
1261 /* Output a warning if the bug is triggered */
1264 Warning ("6502 indirect jump bug triggered at $%04X, ind addr = $%04X",
1271 Regs.PC = MemReadWord(Lo);
1274 ParaVirtHooks (&Regs);
1279 static void OPC_65C02_6C (void)
1280 /* Opcode $6C: JMP (ind) */
1282 /* 6502 bug fixed here */
1284 Regs.PC = MemReadWord (MemReadWord (Regs.PC+1));
1286 ParaVirtHooks (&Regs);
1291 static void OPC_6502_6D (void)
1292 /* Opcode $6D: ADC abs */
1296 Addr = MemReadWord (Regs.PC+1);
1297 ADC (MemReadByte (Addr));
1303 static void OPC_6502_6E (void)
1304 /* Opcode $6E: ROR abs */
1309 Addr = MemReadWord (Regs.PC+1);
1310 Val = MemReadByte (Addr);
1312 MemWriteByte (Addr, Val);
1318 static void OPC_6502_70 (void)
1319 /* Opcode $70: BVS */
1326 static void OPC_6502_71 (void)
1327 /* Opcode $71: ADC (zp),y */
1329 unsigned char ZPAddr;
1332 ZPAddr = MemReadByte (Regs.PC+1);
1333 Addr = MemReadZPWord (ZPAddr);
1334 if (PAGE_CROSS (Addr, Regs.YR)) {
1337 ADC (MemReadByte (Addr + Regs.YR));
1343 static void OPC_65SC02_72 (void)
1344 /* Opcode $72: ADC (zp) */
1346 unsigned char ZPAddr;
1349 ZPAddr = MemReadByte (Regs.PC+1);
1350 Addr = MemReadZPWord (ZPAddr);
1351 ADC (MemReadByte (Addr));
1357 static void OPC_65SC02_74 (void)
1358 /* Opcode $74: STZ zp,x */
1360 unsigned char ZPAddr;
1362 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1363 MemWriteByte (ZPAddr, 0);
1369 static void OPC_6502_75 (void)
1370 /* Opcode $75: ADC zp,x */
1372 unsigned char ZPAddr;
1374 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1375 ADC (MemReadByte (ZPAddr));
1381 static void OPC_6502_76 (void)
1382 /* Opcode $76: ROR zp,x */
1384 unsigned char ZPAddr;
1387 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1388 Val = MemReadByte (ZPAddr);
1390 MemWriteByte (ZPAddr, Val);
1396 static void OPC_6502_78 (void)
1397 /* Opcode $78: SEI */
1406 static void OPC_6502_79 (void)
1407 /* Opcode $79: ADC abs,y */
1411 Addr = MemReadWord (Regs.PC+1);
1412 if (PAGE_CROSS (Addr, Regs.YR)) {
1415 ADC (MemReadByte (Addr + Regs.YR));
1421 static void OPC_65SC02_7A (void)
1422 /* Opcode $7A: PLY */
1433 static void OPC_65SC02_7C (void)
1434 /* Opcode $7C: JMP (ind,X) */
1439 Adr = MemReadWord (PC+1);
1440 Regs.PC = MemReadWord(Adr+Regs.XR);
1442 ParaVirtHooks (&Regs);
1447 static void OPC_6502_7D (void)
1448 /* Opcode $7D: ADC abs,x */
1452 Addr = MemReadWord (Regs.PC+1);
1453 if (PAGE_CROSS (Addr, Regs.XR)) {
1456 ADC (MemReadByte (Addr + Regs.XR));
1462 static void OPC_6502_7E (void)
1463 /* Opcode $7E: ROR abs,x */
1468 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
1469 if (CPU != CPU_6502 && !PAGE_CROSS (Addr, Regs.XR))
1471 Val = MemReadByte (Addr);
1473 MemWriteByte (Addr, Val);
1479 static void OPC_65SC02_80 (void)
1480 /* Opcode $80: BRA */
1487 static void OPC_6502_81 (void)
1488 /* Opcode $81: STA (zp,x) */
1490 unsigned char ZPAddr;
1493 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1494 Addr = MemReadZPWord (ZPAddr);
1495 MemWriteByte (Addr, Regs.AC);
1501 static void OPC_6502_84 (void)
1502 /* Opcode $84: STY zp */
1504 unsigned char ZPAddr;
1506 ZPAddr = MemReadByte (Regs.PC+1);
1507 MemWriteByte (ZPAddr, Regs.YR);
1513 static void OPC_6502_85 (void)
1514 /* Opcode $85: STA zp */
1516 unsigned char ZPAddr;
1518 ZPAddr = MemReadByte (Regs.PC+1);
1519 MemWriteByte (ZPAddr, Regs.AC);
1525 static void OPC_6502_86 (void)
1526 /* Opcode $86: STX zp */
1528 unsigned char ZPAddr;
1530 ZPAddr = MemReadByte (Regs.PC+1);
1531 MemWriteByte (ZPAddr, Regs.XR);
1537 static void OPC_6502_88 (void)
1538 /* Opcode $88: DEY */
1541 Regs.YR = (Regs.YR - 1) & 0xFF;
1549 static void OPC_65SC02_89 (void)
1550 /* Opcode $89: BIT #imm */
1554 Val = MemReadByte (Regs.PC+1);
1555 SET_SF (Val & 0x80);
1556 SET_OF (Val & 0x40);
1557 SET_ZF ((Val & Regs.AC) == 0);
1563 static void OPC_6502_8A (void)
1564 /* Opcode $8A: TXA */
1575 static void OPC_6502_8C (void)
1576 /* Opcode $8C: STY abs */
1580 Addr = MemReadWord (Regs.PC+1);
1581 MemWriteByte (Addr, Regs.YR);
1587 static void OPC_6502_8D (void)
1588 /* Opcode $8D: STA abs */
1592 Addr = MemReadWord (Regs.PC+1);
1593 MemWriteByte (Addr, Regs.AC);
1599 static void OPC_6502_8E (void)
1600 /* Opcode $8E: STX abs */
1604 Addr = MemReadWord (Regs.PC+1);
1605 MemWriteByte (Addr, Regs.XR);
1611 static void OPC_6502_90 (void)
1612 /* Opcode $90: BCC */
1614 BRANCH (!GET_CF ());
1619 static void OPC_6502_91 (void)
1620 /* Opcode $91: sta (zp),y */
1622 unsigned char ZPAddr;
1625 ZPAddr = MemReadByte (Regs.PC+1);
1626 Addr = MemReadZPWord (ZPAddr) + Regs.YR;
1627 MemWriteByte (Addr, Regs.AC);
1633 static void OPC_65SC02_92 (void)
1634 /* Opcode $92: sta (zp) */
1636 unsigned char ZPAddr;
1639 ZPAddr = MemReadByte (Regs.PC+1);
1640 Addr = MemReadZPWord (ZPAddr);
1641 MemWriteByte (Addr, Regs.AC);
1647 static void OPC_6502_94 (void)
1648 /* Opcode $94: STY zp,x */
1650 unsigned char ZPAddr;
1652 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1653 MemWriteByte (ZPAddr, Regs.YR);
1659 static void OPC_6502_95 (void)
1660 /* Opcode $95: STA zp,x */
1662 unsigned char ZPAddr;
1664 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1665 MemWriteByte (ZPAddr, Regs.AC);
1671 static void OPC_6502_96 (void)
1672 /* Opcode $96: stx zp,y */
1674 unsigned char ZPAddr;
1676 ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR;
1677 MemWriteByte (ZPAddr, Regs.XR);
1683 static void OPC_6502_98 (void)
1684 /* Opcode $98: TYA */
1695 static void OPC_6502_99 (void)
1696 /* Opcode $99: STA abs,y */
1700 Addr = MemReadWord (Regs.PC+1) + Regs.YR;
1701 MemWriteByte (Addr, Regs.AC);
1707 static void OPC_6502_9A (void)
1708 /* Opcode $9A: TXS */
1717 static void OPC_65SC02_9C (void)
1718 /* Opcode $9C: STZ abs */
1722 Addr = MemReadWord (Regs.PC+1);
1723 MemWriteByte (Addr, 0);
1729 static void OPC_6502_9D (void)
1730 /* Opcode $9D: STA abs,x */
1734 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
1735 MemWriteByte (Addr, Regs.AC);
1741 static void OPC_65SC02_9E (void)
1742 /* Opcode $9E: STZ abs,x */
1746 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
1747 MemWriteByte (Addr, 0);
1753 static void OPC_6502_A0 (void)
1754 /* Opcode $A0: LDY #imm */
1757 Regs.YR = MemReadByte (Regs.PC+1);
1765 static void OPC_6502_A1 (void)
1766 /* Opcode $A1: LDA (zp,x) */
1768 unsigned char ZPAddr;
1771 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1772 Addr = MemReadZPWord (ZPAddr);
1773 Regs.AC = MemReadByte (Addr);
1781 static void OPC_6502_A2 (void)
1782 /* Opcode $A2: LDX #imm */
1785 Regs.XR = MemReadByte (Regs.PC+1);
1793 static void OPC_6502_A4 (void)
1794 /* Opcode $A4: LDY zp */
1796 unsigned char ZPAddr;
1798 ZPAddr = MemReadByte (Regs.PC+1);
1799 Regs.YR = MemReadByte (ZPAddr);
1807 static void OPC_6502_A5 (void)
1808 /* Opcode $A5: LDA zp */
1810 unsigned char ZPAddr;
1812 ZPAddr = MemReadByte (Regs.PC+1);
1813 Regs.AC = MemReadByte (ZPAddr);
1821 static void OPC_6502_A6 (void)
1822 /* Opcode $A6: LDX zp */
1824 unsigned char ZPAddr;
1826 ZPAddr = MemReadByte (Regs.PC+1);
1827 Regs.XR = MemReadByte (ZPAddr);
1835 static void OPC_6502_A8 (void)
1836 /* Opcode $A8: TAY */
1847 static void OPC_6502_A9 (void)
1848 /* Opcode $A9: LDA #imm */
1851 Regs.AC = MemReadByte (Regs.PC+1);
1859 static void OPC_6502_AA (void)
1860 /* Opcode $AA: TAX */
1871 static void OPC_6502_AC (void)
1872 /* Opcode $Regs.AC: LDY abs */
1876 Addr = MemReadWord (Regs.PC+1);
1877 Regs.YR = MemReadByte (Addr);
1885 static void OPC_6502_AD (void)
1886 /* Opcode $AD: LDA abs */
1890 Addr = MemReadWord (Regs.PC+1);
1891 Regs.AC = MemReadByte (Addr);
1899 static void OPC_6502_AE (void)
1900 /* Opcode $AE: LDX abs */
1904 Addr = MemReadWord (Regs.PC+1);
1905 Regs.XR = MemReadByte (Addr);
1913 static void OPC_6502_B0 (void)
1914 /* Opcode $B0: BCS */
1921 static void OPC_6502_B1 (void)
1922 /* Opcode $B1: LDA (zp),y */
1924 unsigned char ZPAddr;
1927 ZPAddr = MemReadByte (Regs.PC+1);
1928 Addr = MemReadZPWord (ZPAddr);
1929 if (PAGE_CROSS (Addr, Regs.YR)) {
1932 Regs.AC = MemReadByte (Addr + Regs.YR);
1940 static void OPC_65SC02_B2 (void)
1941 /* Opcode $B2: LDA (zp) */
1943 unsigned char ZPAddr;
1946 ZPAddr = MemReadByte (Regs.PC+1);
1947 Addr = MemReadZPWord (ZPAddr);
1948 Regs.AC = MemReadByte (Addr);
1956 static void OPC_6502_B4 (void)
1957 /* Opcode $B4: LDY zp,x */
1959 unsigned char ZPAddr;
1961 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1962 Regs.YR = MemReadByte (ZPAddr);
1970 static void OPC_6502_B5 (void)
1971 /* Opcode $B5: LDA zp,x */
1973 unsigned char ZPAddr;
1975 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1976 Regs.AC = MemReadByte (ZPAddr);
1984 static void OPC_6502_B6 (void)
1985 /* Opcode $B6: LDX zp,y */
1987 unsigned char ZPAddr;
1989 ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR;
1990 Regs.XR = MemReadByte (ZPAddr);
1998 static void OPC_6502_B8 (void)
1999 /* Opcode $B8: CLV */
2008 static void OPC_6502_B9 (void)
2009 /* Opcode $B9: LDA abs,y */
2013 Addr = MemReadWord (Regs.PC+1);
2014 if (PAGE_CROSS (Addr, Regs.YR)) {
2017 Regs.AC = MemReadByte (Addr + Regs.YR);
2025 static void OPC_6502_BA (void)
2026 /* Opcode $BA: TSX */
2029 Regs.XR = Regs.SP & 0xFF;
2037 static void OPC_6502_BC (void)
2038 /* Opcode $BC: LDY abs,x */
2042 Addr = MemReadWord (Regs.PC+1);
2043 if (PAGE_CROSS (Addr, Regs.XR)) {
2046 Regs.YR = MemReadByte (Addr + Regs.XR);
2054 static void OPC_6502_BD (void)
2055 /* Opcode $BD: LDA abs,x */
2059 Addr = MemReadWord (Regs.PC+1);
2060 if (PAGE_CROSS (Addr, Regs.XR)) {
2063 Regs.AC = MemReadByte (Addr + Regs.XR);
2071 static void OPC_6502_BE (void)
2072 /* Opcode $BE: LDX abs,y */
2076 Addr = MemReadWord (Regs.PC+1);
2077 if (PAGE_CROSS (Addr, Regs.YR)) {
2080 Regs.XR = MemReadByte (Addr + Regs.YR);
2088 static void OPC_6502_C0 (void)
2089 /* Opcode $C0: CPY #imm */
2092 CMP (Regs.YR, MemReadByte (Regs.PC+1));
2098 static void OPC_6502_C1 (void)
2099 /* Opcode $C1: CMP (zp,x) */
2101 unsigned char ZPAddr;
2104 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
2105 Addr = MemReadZPWord (ZPAddr);
2106 CMP (Regs.AC, MemReadByte (Addr));
2112 static void OPC_6502_C4 (void)
2113 /* Opcode $C4: CPY zp */
2115 unsigned char ZPAddr;
2117 ZPAddr = MemReadByte (Regs.PC+1);
2118 CMP (Regs.YR, MemReadByte (ZPAddr));
2124 static void OPC_6502_C5 (void)
2125 /* Opcode $C5: CMP zp */
2127 unsigned char ZPAddr;
2129 ZPAddr = MemReadByte (Regs.PC+1);
2130 CMP (Regs.AC, MemReadByte (ZPAddr));
2136 static void OPC_6502_C6 (void)
2137 /* Opcode $C6: DEC zp */
2139 unsigned char ZPAddr;
2142 ZPAddr = MemReadByte (Regs.PC+1);
2143 Val = MemReadByte (ZPAddr) - 1;
2144 MemWriteByte (ZPAddr, Val);
2152 static void OPC_6502_C8 (void)
2153 /* Opcode $C8: INY */
2156 Regs.YR = (Regs.YR + 1) & 0xFF;
2164 static void OPC_6502_C9 (void)
2165 /* Opcode $C9: CMP #imm */
2168 CMP (Regs.AC, MemReadByte (Regs.PC+1));
2174 static void OPC_6502_CA (void)
2175 /* Opcode $CA: DEX */
2178 Regs.XR = (Regs.XR - 1) & 0xFF;
2186 static void OPC_6502_CC (void)
2187 /* Opcode $CC: CPY abs */
2191 Addr = MemReadWord (Regs.PC+1);
2192 CMP (Regs.YR, MemReadByte (Addr));
2198 static void OPC_6502_CD (void)
2199 /* Opcode $CD: CMP abs */
2203 Addr = MemReadWord (Regs.PC+1);
2204 CMP (Regs.AC, MemReadByte (Addr));
2210 static void OPC_6502_CE (void)
2211 /* Opcode $CE: DEC abs */
2216 Addr = MemReadWord (Regs.PC+1);
2217 Val = MemReadByte (Addr) - 1;
2218 MemWriteByte (Addr, Val);
2226 static void OPC_6502_D0 (void)
2227 /* Opcode $D0: BNE */
2229 BRANCH (!GET_ZF ());
2234 static void OPC_6502_D1 (void)
2235 /* Opcode $D1: CMP (zp),y */
2240 ZPAddr = MemReadByte (Regs.PC+1);
2241 Addr = MemReadWord (ZPAddr);
2242 if (PAGE_CROSS (Addr, Regs.YR)) {
2245 CMP (Regs.AC, MemReadByte (Addr + Regs.YR));
2251 static void OPC_65SC02_D2 (void)
2252 /* Opcode $D2: CMP (zp) */
2257 ZPAddr = MemReadByte (Regs.PC+1);
2258 Addr = MemReadWord (ZPAddr);
2259 CMP (Regs.AC, MemReadByte (Addr));
2265 static void OPC_6502_D5 (void)
2266 /* Opcode $D5: CMP zp,x */
2268 unsigned char ZPAddr;
2270 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
2271 CMP (Regs.AC, MemReadByte (ZPAddr));
2277 static void OPC_6502_D6 (void)
2278 /* Opcode $D6: DEC zp,x */
2280 unsigned char ZPAddr;
2283 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
2284 Val = MemReadByte (ZPAddr) - 1;
2285 MemWriteByte (ZPAddr, Val);
2293 static void OPC_6502_D8 (void)
2294 /* Opcode $D8: CLD */
2303 static void OPC_6502_D9 (void)
2304 /* Opcode $D9: CMP abs,y */
2308 Addr = MemReadWord (Regs.PC+1);
2309 if (PAGE_CROSS (Addr, Regs.YR)) {
2312 CMP (Regs.AC, MemReadByte (Addr + Regs.YR));
2318 static void OPC_65SC02_DA (void)
2319 /* Opcode $DA: PHX */
2328 static void OPC_6502_DD (void)
2329 /* Opcode $DD: CMP abs,x */
2333 Addr = MemReadWord (Regs.PC+1);
2334 if (PAGE_CROSS (Addr, Regs.XR)) {
2337 CMP (Regs.AC, MemReadByte (Addr + Regs.XR));
2343 static void OPC_6502_DE (void)
2344 /* Opcode $DE: DEC abs,x */
2349 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
2350 Val = MemReadByte (Addr) - 1;
2351 MemWriteByte (Addr, Val);
2359 static void OPC_6502_E0 (void)
2360 /* Opcode $E0: CPX #imm */
2363 CMP (Regs.XR, MemReadByte (Regs.PC+1));
2369 static void OPC_6502_E1 (void)
2370 /* Opcode $E1: SBC (zp,x) */
2372 unsigned char ZPAddr;
2375 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
2376 Addr = MemReadZPWord (ZPAddr);
2377 SBC (MemReadByte (Addr));
2383 static void OPC_6502_E4 (void)
2384 /* Opcode $E4: CPX zp */
2386 unsigned char ZPAddr;
2388 ZPAddr = MemReadByte (Regs.PC+1);
2389 CMP (Regs.XR, MemReadByte (ZPAddr));
2395 static void OPC_6502_E5 (void)
2396 /* Opcode $E5: SBC zp */
2398 unsigned char ZPAddr;
2400 ZPAddr = MemReadByte (Regs.PC+1);
2401 SBC (MemReadByte (ZPAddr));
2407 static void OPC_6502_E6 (void)
2408 /* Opcode $E6: INC zp */
2410 unsigned char ZPAddr;
2413 ZPAddr = MemReadByte (Regs.PC+1);
2414 Val = MemReadByte (ZPAddr) + 1;
2415 MemWriteByte (ZPAddr, Val);
2423 static void OPC_6502_E8 (void)
2424 /* Opcode $E8: INX */
2427 Regs.XR = (Regs.XR + 1) & 0xFF;
2435 static void OPC_6502_E9 (void)
2436 /* Opcode $E9: SBC #imm */
2439 SBC (MemReadByte (Regs.PC+1));
2445 static void OPC_6502_EA (void)
2446 /* Opcode $EA: NOP */
2448 /* This one is easy... */
2455 static void OPC_65C02_NOP11(void)
2456 /* Opcode 'Illegal' 1 cycle NOP */
2464 static void OPC_65C02_NOP22 (void)
2465 /* Opcode 'Illegal' 2 byte 2 cycle NOP */
2473 static void OPC_65C02_NOP24 (void)
2474 /* Opcode 'Illegal' 2 byte 4 cycle NOP */
2482 static void OPC_65C02_NOP34 (void)
2483 /* Opcode 'Illegal' 3 byte 4 cycle NOP */
2491 static void OPC_6502_EC (void)
2492 /* Opcode $EC: CPX abs */
2496 Addr = MemReadWord (Regs.PC+1);
2497 CMP (Regs.XR, MemReadByte (Addr));
2503 static void OPC_6502_ED (void)
2504 /* Opcode $ED: SBC abs */
2508 Addr = MemReadWord (Regs.PC+1);
2509 SBC (MemReadByte (Addr));
2515 static void OPC_6502_EE (void)
2516 /* Opcode $EE: INC abs */
2521 Addr = MemReadWord (Regs.PC+1);
2522 Val = MemReadByte (Addr) + 1;
2523 MemWriteByte (Addr, Val);
2531 static void OPC_6502_F0 (void)
2532 /* Opcode $F0: BEQ */
2539 static void OPC_6502_F1 (void)
2540 /* Opcode $F1: SBC (zp),y */
2542 unsigned char ZPAddr;
2545 ZPAddr = MemReadByte (Regs.PC+1);
2546 Addr = MemReadZPWord (ZPAddr);
2547 if (PAGE_CROSS (Addr, Regs.YR)) {
2550 SBC (MemReadByte (Addr + Regs.YR));
2556 static void OPC_65SC02_F2 (void)
2557 /* Opcode $F2: SBC (zp) */
2559 unsigned char ZPAddr;
2562 ZPAddr = MemReadByte (Regs.PC+1);
2563 Addr = MemReadZPWord (ZPAddr);
2564 SBC (MemReadByte (Addr));
2570 static void OPC_6502_F5 (void)
2571 /* Opcode $F5: SBC zp,x */
2573 unsigned char ZPAddr;
2575 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
2576 SBC (MemReadByte (ZPAddr));
2582 static void OPC_6502_F6 (void)
2583 /* Opcode $F6: INC zp,x */
2585 unsigned char ZPAddr;
2588 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
2589 Val = MemReadByte (ZPAddr) + 1;
2590 MemWriteByte (ZPAddr, Val);
2598 static void OPC_6502_F8 (void)
2599 /* Opcode $F8: SED */
2608 static void OPC_6502_F9 (void)
2609 /* Opcode $F9: SBC abs,y */
2613 Addr = MemReadWord (Regs.PC+1);
2614 if (PAGE_CROSS (Addr, Regs.YR)) {
2617 SBC (MemReadByte (Addr + Regs.YR));
2623 static void OPC_65SC02_FA (void)
2624 /* Opcode $7A: PLX */
2635 static void OPC_6502_FD (void)
2636 /* Opcode $FD: SBC abs,x */
2640 Addr = MemReadWord (Regs.PC+1);
2641 if (PAGE_CROSS (Addr, Regs.XR)) {
2644 SBC (MemReadByte (Addr + Regs.XR));
2650 static void OPC_6502_FE (void)
2651 /* Opcode $FE: INC abs,x */
2656 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
2657 Val = MemReadByte (Addr) + 1;
2658 MemWriteByte (Addr, Val);
2666 /*****************************************************************************/
2667 /* Opcode handler tables */
2668 /*****************************************************************************/
2672 /* Opcode handler table for the 6502 */
2673 static const OPFunc OP6502Table[256] = {
2934 /* Opcode handler table for the 65C02 */
2935 static const OPFunc OP65C02Table[256] = {
2938 OPC_65C02_NOP22, // $02
2939 OPC_65C02_NOP11, // $03
2943 OPC_Illegal, // $07: RMB0 currently unsupported
2947 OPC_65C02_NOP11, // $0B
2951 OPC_Illegal, // $0F: BBR0 currently unsupported
2955 OPC_65C02_NOP11, // $13
2959 OPC_Illegal, // $17: RMB1 currently unsupported
2963 OPC_65C02_NOP11, // $1B
2967 OPC_Illegal, // $1F: BBR1 currently unsupported
2970 OPC_65C02_NOP22, // $22
2971 OPC_65C02_NOP11, // $23
2975 OPC_Illegal, // $27: RMB2 currently unsupported
2979 OPC_65C02_NOP11, // $2B
2983 OPC_Illegal, // $2F: BBR2 currently unsupported
2987 OPC_65C02_NOP11, // $33
2991 OPC_Illegal, // $37: RMB3 currently unsupported
2995 OPC_65C02_NOP11, // $3B
2999 OPC_Illegal, // $3F: BBR3 currently unsupported
3002 OPC_65C02_NOP22, // $42
3003 OPC_65C02_NOP11, // $43
3004 OPC_65C02_44, // $44
3007 OPC_Illegal, // $47: RMB4 currently unsupported
3011 OPC_65C02_NOP11, // $4B
3015 OPC_Illegal, // $4F: BBR4 currently unsupported
3019 OPC_65C02_NOP11, // $53
3020 OPC_65C02_NOP24, // $54
3023 OPC_Illegal, // $57: RMB5 currently unsupported
3027 OPC_65C02_NOP11, // $5B
3031 OPC_Illegal, // $5F: BBR5 currently unsupported
3034 OPC_65C02_NOP22, // $62
3035 OPC_65C02_NOP11, // $63
3039 OPC_Illegal, // $67: RMB6 currently unsupported
3043 OPC_65C02_NOP11, // $6B
3047 OPC_Illegal, // $6F: BBR6 currently unsupported
3051 OPC_65C02_NOP11, // $73
3055 OPC_Illegal, // $77: RMB7 currently unsupported
3059 OPC_65C02_NOP11, // $7B
3063 OPC_Illegal, // $7F: BBR7 currently unsupported
3066 OPC_65C02_NOP22, // $82
3067 OPC_65C02_NOP11, // $83
3071 OPC_Illegal, // $87: SMB0 currently unsupported
3075 OPC_65C02_NOP11, // $8B
3079 OPC_Illegal, // $8F: BBS0 currently unsupported
3083 OPC_65C02_NOP11, // $93
3087 OPC_Illegal, // $97: SMB1 currently unsupported
3091 OPC_65C02_NOP11, // $9B
3095 OPC_Illegal, // $9F: BBS1 currently unsupported
3099 OPC_65C02_NOP11, // $A3
3103 OPC_Illegal, // $A7: SMB2 currently unsupported
3107 OPC_65C02_NOP11, // $AB
3111 OPC_Illegal, // $AF: BBS2 currently unsupported
3115 OPC_65C02_NOP11, // $B3
3119 OPC_Illegal, // $B7: SMB3 currently unsupported
3123 OPC_65C02_NOP11, // $BB
3127 OPC_Illegal, // $BF: BBS3 currently unsupported
3130 OPC_65C02_NOP22, // $C2
3131 OPC_65C02_NOP11, // $C3
3135 OPC_Illegal, // $C7: SMB4 currently unsupported
3139 OPC_Illegal, // $CB: WAI currently unsupported
3143 OPC_Illegal, // $CF: BBS4 currently unsupported
3147 OPC_65C02_NOP11, // $D3
3148 OPC_65C02_NOP24, // $D4
3151 OPC_Illegal, // $D7: SMB5 currently unsupported
3155 OPC_Illegal, // $DB: STP currently unsupported
3156 OPC_65C02_NOP34, // $DC
3159 OPC_Illegal, // $DF: BBS5 currently unsupported
3162 OPC_65C02_NOP22, // $E2
3163 OPC_65C02_NOP11, // $E3
3167 OPC_Illegal, // $E7: SMB6 currently unsupported
3171 OPC_65C02_NOP11, // $EB
3175 OPC_Illegal, // $EF: BBS6 currently unsupported
3179 OPC_65C02_NOP11, // $F3
3180 OPC_65C02_NOP24, // $F4
3183 OPC_Illegal, // $F7: SMB7 currently unsupported
3187 OPC_65C02_NOP11, // $FB
3188 OPC_65C02_NOP34, // $FC
3191 OPC_Illegal, // $FF: BBS7 currently unsupported
3196 /* Tables with opcode handlers */
3197 static const OPFunc* Handlers[2] = {OP6502Table, OP65C02Table};
3201 /*****************************************************************************/
3203 /*****************************************************************************/
3207 void IRQRequest (void)
3208 /* Generate an IRQ */
3210 /* Remember the request */
3216 void NMIRequest (void)
3217 /* Generate an NMI */
3219 /* Remember the request */
3226 /* Generate a CPU RESET */
3232 /* Bits 5 and 4 aren't used, and always are 1! */
3234 Regs.PC = MemReadWord (0xFFFC);
3239 unsigned ExecuteInsn (void)
3240 /* Execute one CPU instruction */
3242 /* If we have an NMI request, handle it */
3243 if (HaveNMIRequest) {
3248 PUSH (Regs.SR & ~BF);
3250 if (CPU != CPU_6502)
3254 Regs.PC = MemReadWord (0xFFFA);
3257 } else if (HaveIRQRequest && GET_IF () == 0) {
3262 PUSH (Regs.SR & ~BF);
3264 if (CPU != CPU_6502)
3268 Regs.PC = MemReadWord (0xFFFE);
3273 /* Normal instruction - read the next opcode */
3274 unsigned char OPC = MemReadByte (Regs.PC);
3277 Handlers[CPU][OPC] ();
3281 TotalCycles += Cycles;
3283 /* Return the number of clock cycles needed by this insn */
3289 unsigned long GetCycles (void)
3290 /* Return the total number of cycles executed */
3292 /* Return the total number of cycles */