1/*****************************************************************************/
2/* */
3/* 6502.c */
4/* */
5/* CPU core for the 6502 */
6/* */
7/* */
8/* */
9/* (C) 2003-2012, Ullrich von Bassewitz */
10/* Roemerstrasse 52 */
11/* D-70794 Filderstadt */
12/* EMail: uz@cc65.org */
13/* */
14/* Mar-2017, Christian Krueger, added support for 65SC02 */
15/* */
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. */
19/* */
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: */
23/* */
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 */
31/* distribution. */
32/* */
33/*****************************************************************************/
34
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
39 6502)
40*/
41
42#include "memory.h"
43#include "error.h"
44#include "6502.h"
45#include "paravirt.h"
46
47
48
49/*****************************************************************************/
50/* Data */
51/*****************************************************************************/
52
53
54
55/* Current CPU */
56CPUType CPU;
57
58/* Type of an opcode handler function */
59typedef void (*OPFunc) (void);
60
61/* The CPU registers */
62static CPURegs Regs;
63
64/* Cycles for the current insn */
65static unsigned Cycles;
66
67/* Total number of CPU cycles exec'd */
68static unsigned long TotalCycles;
69
70/* NMI request active */
71static unsigned HaveNMIRequest;
72
73/* IRQ request active */
74static unsigned HaveIRQRequest;
75
76/* flag to print cycles at program termination */
77int PrintCycles;
78
79
80/*****************************************************************************/
81/* Helper functions and macros */
82/*****************************************************************************/
83
84
85
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)
93
94/* Set the flags. The parameter is a boolean flag that says if the flag should be
95** set or reset.
96*/
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)
103
104/* Special test and set macros. The meaning of the parameter depends on the
105** actual flag that should be set or reset.
106*/
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)
110
111/* Program counter halves */
112#define PCL (Regs.PC & 0xFF)
113#define PCH ((Regs.PC >> 8) & 0xFF)
114
115/* Stack operations */
116#define PUSH(Val) MemWriteByte (0x0100 | (Regs.SP-- & 0xFF), Val)
117#define POP() MemReadByte (0x0100 | (++Regs.SP & 0xFF))
118
119/* Test for page cross */
120#define PAGE_CROSS(addr,offs) ((((addr) & 0xFF) + offs) >= 0x100)
121
122/* #imm */
123#define AC_OP_IMM(op) \
124 Cycles = 2; \
125 Regs.AC = Regs.AC op MemReadByte (Regs.PC+1); \
126 TEST_ZF (Regs.AC); \
127 TEST_SF (Regs.AC); \
128 Regs.PC += 2
129
130/* zp */
131#define AC_OP_ZP(op) \
132 Cycles = 3; \
133 Regs.AC = Regs.AC op MemReadByte (MemReadByte (Regs.PC+1)); \
134 TEST_ZF (Regs.AC); \
135 TEST_SF (Regs.AC); \
136 Regs.PC += 2
137
138/* zp,x */
139#define AC_OP_ZPX(op) \
140 unsigned char ZPAddr; \
141 Cycles = 4; \
142 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; \
143 Regs.AC = Regs.AC op MemReadByte (ZPAddr); \
144 TEST_ZF (Regs.AC); \
145 TEST_SF (Regs.AC); \
146 Regs.PC += 2
147
148/* zp,y */
149#define AC_OP_ZPY(op) \
150 unsigned char ZPAddr; \
151 Cycles = 4; \
152 ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR; \
153 Regs.AC = Regs.AC op MemReadByte (ZPAddr); \
154 TEST_ZF (Regs.AC); \
155 TEST_SF (Regs.AC); \
156 Regs.PC += 2
157
158/* abs */
159#define AC_OP_ABS(op) \
160 unsigned Addr; \
161 Cycles = 4; \
162 Addr = MemReadWord (Regs.PC+1); \
163 Regs.AC = Regs.AC op MemReadByte (Addr); \
164 TEST_ZF (Regs.AC); \
165 TEST_SF (Regs.AC); \
166 Regs.PC += 3
167
168/* abs,x */
169#define AC_OP_ABSX(op) \
170 unsigned Addr; \
171 Cycles = 4; \
172 Addr = MemReadWord (Regs.PC+1); \
173 if (PAGE_CROSS (Addr, Regs.XR)) { \
174 ++Cycles; \
175 } \
176 Regs.AC = Regs.AC op MemReadByte (Addr + Regs.XR); \
177 TEST_ZF (Regs.AC); \
178 TEST_SF (Regs.AC); \
179 Regs.PC += 3
180
181/* abs,y */
182#define AC_OP_ABSY(op) \
183 unsigned Addr; \
184 Cycles = 4; \
185 Addr = MemReadWord (Regs.PC+1); \
186 if (PAGE_CROSS (Addr, Regs.YR)) { \
187 ++Cycles; \
188 } \
189 Regs.AC = Regs.AC op MemReadByte (Addr + Regs.YR); \
190 TEST_ZF (Regs.AC); \
191 TEST_SF (Regs.AC); \
192 Regs.PC += 3
193
194/* (zp,x) */
195#define AC_OP_ZPXIND(op) \
196 unsigned char ZPAddr; \
197 unsigned Addr; \
198 Cycles = 6; \
199 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; \
200 Addr = MemReadZPWord (ZPAddr); \
201 Regs.AC = Regs.AC op MemReadByte (Addr); \
202 TEST_ZF (Regs.AC); \
203 TEST_SF (Regs.AC); \
204 Regs.PC += 2
205
206/* (zp),y */
207#define AC_OP_ZPINDY(op) \
208 unsigned char ZPAddr; \
209 unsigned Addr; \
210 Cycles = 5; \
211 ZPAddr = MemReadByte (Regs.PC+1); \
212 Addr = MemReadZPWord (ZPAddr); \
213 if (PAGE_CROSS (Addr, Regs.YR)) { \
214 ++Cycles; \
215 } \
216 Addr += Regs.YR; \
217 Regs.AC = Regs.AC op MemReadByte (Addr); \
218 TEST_ZF (Regs.AC); \
219 TEST_SF (Regs.AC); \
220 Regs.PC += 2
221
222/* (zp) */
223#define AC_OP_ZPIND(op) \
224 unsigned char ZPAddr; \
225 unsigned Addr; \
226 Cycles = 5; \
227 ZPAddr = MemReadByte (Regs.PC+1); \
228 Addr = MemReadZPWord (ZPAddr); \
229 Regs.AC = Regs.AC op MemReadByte (Addr); \
230 TEST_ZF (Regs.AC); \
231 TEST_SF (Regs.AC); \
232 Regs.PC += 2
233
234/* ADC */
235#define ADC(v) \
236 do { \
237 unsigned old = Regs.AC; \
238 unsigned rhs = (v & 0xFF); \
239 if (GET_DF ()) { \
240 unsigned lo; \
241 int res; \
242 lo = (old & 0x0F) + (rhs & 0x0F) + GET_CF (); \
243 if (lo >= 0x0A) { \
244 lo = ((lo + 0x06) & 0x0F) + 0x10; \
245 } \
246 Regs.AC = (old & 0xF0) + (rhs & 0xF0) + lo; \
247 res = (signed char)(old & 0xF0) + \
248 (signed char)(rhs & 0xF0) + \
249 (signed char)lo; \
250 TEST_ZF (old + rhs + GET_CF ()); \
251 TEST_SF (Regs.AC); \
252 if (Regs.AC >= 0xA0) { \
253 Regs.AC += 0x60; \
254 } \
255 TEST_CF (Regs.AC); \
256 SET_OF ((res < -128) || (res > 127)); \
257 if (CPU != CPU_6502) { \
258 ++Cycles; \
259 } \
260 } else { \
261 Regs.AC += rhs + GET_CF (); \
262 TEST_ZF (Regs.AC); \
263 TEST_SF (Regs.AC); \
264 TEST_CF (Regs.AC); \
265 SET_OF (!((old ^ rhs) & 0x80) && \
266 ((old ^ Regs.AC) & 0x80)); \
267 Regs.AC &= 0xFF; \
268 } \
269 } while (0)
270
271/* branches */
272#define BRANCH(cond) \
273 Cycles = 2; \
274 if (cond) { \
275 signed char Offs; \
276 unsigned char OldPCH; \
277 ++Cycles; \
278 Offs = (signed char) MemReadByte (Regs.PC+1); \
279 OldPCH = PCH; \
280 Regs.PC += 2 + (int) Offs; \
281 if (PCH != OldPCH) { \
282 ++Cycles; \
283 } \
284 } else { \
285 Regs.PC += 2; \
286 }
287
288/* compares */
289#define CMP(v1, v2) \
290 do { \
291 unsigned Result = v1 - v2; \
292 TEST_ZF (Result & 0xFF); \
293 TEST_SF (Result); \
294 SET_CF (Result <= 0xFF); \
295 } while (0)
296
297
298/* ROL */
299#define ROL(Val) \
300 Val <<= 1; \
301 if (GET_CF ()) { \
302 Val |= 0x01; \
303 } \
304 TEST_ZF (Val); \
305 TEST_SF (Val); \
306 TEST_CF (Val)
307
308/* ROR */
309#define ROR(Val) \
310 if (GET_CF ()) { \
311 Val |= 0x100; \
312 } \
313 SET_CF (Val & 0x01); \
314 Val >>= 1; \
315 TEST_ZF (Val); \
316 TEST_SF (Val)
317
318/* SBC */
319#define SBC(v) \
320 do { \
321 unsigned old = Regs.AC; \
322 unsigned rhs = (v & 0xFF); \
323 if (GET_DF ()) { \
324 unsigned lo; \
325 int res; \
326 lo = (old & 0x0F) - (rhs & 0x0F) + GET_CF () - 1; \
327 if (lo & 0x80) { \
328 lo = ((lo - 0x06) & 0x0F) - 0x10; \
329 } \
330 Regs.AC = (old & 0xF0) - (rhs & 0xF0) + lo; \
331 if (Regs.AC & 0x80) { \
332 Regs.AC -= 0x60; \
333 } \
334 res = Regs.AC - rhs + (!GET_CF ()); \
335 TEST_ZF (res); \
336 TEST_SF (res); \
337 SET_CF (res <= 0xFF); \
338 SET_OF (((old^rhs) & (old^res) & 0x80)); \
339 if (CPU != CPU_6502) { \
340 ++Cycles; \
341 } \
342 } else { \
343 Regs.AC -= rhs + (!GET_CF ()); \
344 TEST_ZF (Regs.AC); \
345 TEST_SF (Regs.AC); \
346 SET_CF (Regs.AC <= 0xFF); \
347 SET_OF (((old^rhs) & (old^Regs.AC) & 0x80)); \
348 Regs.AC &= 0xFF; \
349 } \
350 } while (0)
351
352
353
354/*****************************************************************************/
355/* Opcode handling functions */
356/*****************************************************************************/
357
358
359
360static void OPC_Illegal (void)
361{
362 Error ("Illegal opcode $%02X at address $%04X",
363 MemReadByte (Regs.PC), Regs.PC);
364}
365
366
367
368static void OPC_6502_00 (void)
369/* Opcode $00: BRK */
370{
371 Cycles = 7;
372 Regs.PC += 2;
373 PUSH (PCH);
374 PUSH (PCL);
375 PUSH (Regs.SR);
376 SET_IF (1);
377 if (CPU != CPU_6502)
378 {
379 SET_DF (0);
380 }
381 Regs.PC = MemReadWord (0xFFFE);
382}
383
384
385
386static void OPC_6502_01 (void)
387/* Opcode $01: ORA (ind,x) */
388{
389 AC_OP_ZPXIND (|);
390}
391
392
393
394static void OPC_65SC02_04 (void)
395/* Opcode $04: TSB zp */
396{
397 unsigned char ZPAddr;
398 unsigned char Val;
399 Cycles = 5;
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));
404 Regs.PC += 2;
405}
406
407
408
409static void OPC_6502_05 (void)
410/* Opcode $05: ORA zp */
411{
412 AC_OP_ZP (|);
413}
414
415
416
417static void OPC_6502_06 (void)
418/* Opcode $06: ASL zp */
419{
420 unsigned char ZPAddr;
421 unsigned Val;
422 Cycles = 5;
423 ZPAddr = MemReadByte (Regs.PC+1);
424 Val = MemReadByte (ZPAddr) << 1;
425 MemWriteByte (ZPAddr, (unsigned char) Val);
426 TEST_ZF (Val & 0xFF);
427 TEST_SF (Val);
428 SET_CF (Val & 0x100);
429 Regs.PC += 2;
430}
431
432
433
434static void OPC_6502_08 (void)
435/* Opcode $08: PHP */
436{
437 Cycles = 3;
438 PUSH (Regs.SR);
439 Regs.PC += 1;
440}
441
442
443
444static void OPC_6502_09 (void)
445/* Opcode $09: ORA #imm */
446{
447 AC_OP_IMM (|);
448}
449
450
451
452static void OPC_6502_0A (void)
453/* Opcode $0A: ASL a */
454{
455 Cycles = 2;
456 Regs.AC <<= 1;
457 TEST_ZF (Regs.AC & 0xFF);
458 TEST_SF (Regs.AC);
459 SET_CF (Regs.AC & 0x100);
460 Regs.AC &= 0xFF;
461 Regs.PC += 1;
462}
463
464
465
466static void OPC_65SC02_0C (void)
467/* Opcode $0C: TSB abs */
468{
469 unsigned Addr;
470 unsigned char Val;
471 Cycles = 6;
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));
476 Regs.PC += 3;
477}
478
479
480
481static void OPC_6502_0D (void)
482/* Opcode $0D: ORA abs */
483{
484 AC_OP_ABS (|);
485}
486
487
488
489static void OPC_6502_0E (void)
490/* Opcode $0E: ALS abs */
491{
492 unsigned Addr;
493 unsigned Val;
494 Cycles = 6;
495 Addr = MemReadWord (Regs.PC+1);
496 Val = MemReadByte (Addr) << 1;
497 MemWriteByte (Addr, (unsigned char) Val);
498 TEST_ZF (Val & 0xFF);
499 TEST_SF (Val);
500 SET_CF (Val & 0x100);
501 Regs.PC += 3;
502}
503
504
505
506static void OPC_6502_10 (void)
507/* Opcode $10: BPL */
508{
509 BRANCH (!GET_SF ());
510}
511
512
513
514static void OPC_6502_11 (void)
515/* Opcode $11: ORA (zp),y */
516{
517 AC_OP_ZPINDY (|);
518}
519
520
521
522static void OPC_65SC02_12 (void)
523/* Opcode $12: ORA (zp) */
524{
525 AC_OP_ZPIND (|);
526}
527
528
529
530static void OPC_65SC02_14 (void)
531/* Opcode $14: TRB zp */
532{
533 unsigned char ZPAddr;
534 unsigned char Val;
535 Cycles = 5;
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));
540 Regs.PC += 2;
541}
542
543
544
545static void OPC_6502_15 (void)
546/* Opcode $15: ORA zp,x */
547{
548 AC_OP_ZPX (|);
549}
550
551
552
553static void OPC_6502_16 (void)
554/* Opcode $16: ASL zp,x */
555{
556 unsigned char ZPAddr;
557 unsigned Val;
558 Cycles = 6;
559 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
560 Val = MemReadByte (ZPAddr) << 1;
561 MemWriteByte (ZPAddr, (unsigned char) Val);
562 TEST_ZF (Val & 0xFF);
563 TEST_SF (Val);
564 SET_CF (Val & 0x100);
565 Regs.PC += 2;
566}
567
568
569
570static void OPC_6502_18 (void)
571/* Opcode $18: CLC */
572{
573 Cycles = 2;
574 SET_CF (0);
575 Regs.PC += 1;
576}
577
578
579
580static void OPC_6502_19 (void)
581/* Opcode $19: ORA abs,y */
582{
583 AC_OP_ABSY (|);
584}
585
586
587
588static void OPC_65SC02_1A (void)
589/* Opcode $1A: INC a */
590{
591 Cycles = 2;
592 Regs.AC = (Regs.AC + 1) & 0xFF;
593 TEST_ZF (Regs.AC);
594 TEST_SF (Regs.AC);
595 Regs.PC += 1;
596}
597
598
599
600static void OPC_65SC02_1C (void)
601/* Opcode $1C: TRB abs */
602{
603 unsigned Addr;
604 unsigned char Val;
605 Cycles = 6;
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));
610 Regs.PC += 3;
611}
612
613
614
615static void OPC_6502_1D (void)
616/* Opcode $1D: ORA abs,x */
617{
618 AC_OP_ABSX (|);
619}
620
621
622
623static void OPC_6502_1E (void)
624/* Opcode $1E: ASL abs,x */
625{
626 unsigned Addr;
627 unsigned Val;
628 Cycles = 7;
629 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
630 if (CPU != CPU_6502 && !PAGE_CROSS (Addr, Regs.XR))
631 --Cycles;
632 Val = MemReadByte (Addr) << 1;
633 MemWriteByte (Addr, (unsigned char) Val);
634 TEST_ZF (Val & 0xFF);
635 TEST_SF (Val);
636 SET_CF (Val & 0x100);
637 Regs.PC += 3;
638}
639
640
641
642static void OPC_6502_20 (void)
643/* Opcode $20: JSR */
644{
645 unsigned Addr;
646 Cycles = 6;
647 Addr = MemReadWord (Regs.PC+1);
648 Regs.PC += 2;
649 PUSH (PCH);
650 PUSH (PCL);
651 Regs.PC = Addr;
652
653 ParaVirtHooks (&Regs);
654}
655
656
657
658static void OPC_6502_21 (void)
659/* Opcode $21: AND (zp,x) */
660{
661 AC_OP_ZPXIND (&);
662}
663
664
665
666static void OPC_6502_24 (void)
667/* Opcode $24: BIT zp */
668{
669 unsigned char ZPAddr;
670 unsigned char Val;
671 Cycles = 3;
672 ZPAddr = MemReadByte (Regs.PC+1);
673 Val = MemReadByte (ZPAddr);
674 SET_SF (Val & 0x80);
675 SET_OF (Val & 0x40);
676 SET_ZF ((Val & Regs.AC) == 0);
677 Regs.PC += 2;
678}
679
680
681
682static void OPC_6502_25 (void)
683/* Opcode $25: AND zp */
684{
685 AC_OP_ZP (&);
686}
687
688
689
690static void OPC_6502_26 (void)
691/* Opcode $26: ROL zp */
692{
693 unsigned char ZPAddr;
694 unsigned Val;
695 Cycles = 5;
696 ZPAddr = MemReadByte (Regs.PC+1);
697 Val = MemReadByte (ZPAddr);
698 ROL (Val);
699 MemWriteByte (ZPAddr, Val);
700 Regs.PC += 2;
701}
702
703
704
705static void OPC_6502_28 (void)
706/* Opcode $28: PLP */
707{
708 Cycles = 4;
709
710 /* Bits 5 and 4 aren't used, and always are 1! */
711 Regs.SR = (POP () | 0x30);
712 Regs.PC += 1;
713}
714
715
716
717static void OPC_6502_29 (void)
718/* Opcode $29: AND #imm */
719{
720 AC_OP_IMM (&);
721}
722
723
724
725static void OPC_6502_2A (void)
726/* Opcode $2A: ROL a */
727{
728 Cycles = 2;
729 ROL (Regs.AC);
730 Regs.AC &= 0xFF;
731 Regs.PC += 1;
732}
733
734
735
736static void OPC_6502_2C (void)
737/* Opcode $2C: BIT abs */
738{
739 unsigned Addr;
740 unsigned char Val;
741 Cycles = 4;
742 Addr = MemReadWord (Regs.PC+1);
743 Val = MemReadByte (Addr);
744 SET_SF (Val & 0x80);
745 SET_OF (Val & 0x40);
746 SET_ZF ((Val & Regs.AC) == 0);
747 Regs.PC += 3;
748}
749
750
751
752static void OPC_6502_2D (void)
753/* Opcode $2D: AND abs */
754{
755 AC_OP_ABS (&);
756}
757
758
759
760static void OPC_6502_2E (void)
761/* Opcode $2E: ROL abs */
762{
763 unsigned Addr;
764 unsigned Val;
765 Cycles = 6;
766 Addr = MemReadWord (Regs.PC+1);
767 Val = MemReadByte (Addr);
768 ROL (Val);
769 MemWriteByte (Addr, Val);
770 Regs.PC += 3;
771}
772
773
774
775static void OPC_6502_30 (void)
776/* Opcode $30: BMI */
777{
778 BRANCH (GET_SF ());
779}
780
781
782
783static void OPC_6502_31 (void)
784/* Opcode $31: AND (zp),y */
785{
786 AC_OP_ZPINDY (&);
787}
788
789
790
791static void OPC_65SC02_32 (void)
792/* Opcode $32: AND (zp) */
793{
794 AC_OP_ZPIND (&);
795}
796
797
798
799static void OPC_65SC02_34 (void)
800/* Opcode $34: BIT zp,x */
801{
802 unsigned char ZPAddr;
803 unsigned char Val;
804 Cycles = 4;
805 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
806 Val = MemReadByte (ZPAddr);
807 SET_SF (Val & 0x80);
808 SET_OF (Val & 0x40);
809 SET_ZF ((Val & Regs.AC) == 0);
810 Regs.PC += 2;
811}
812
813
814
815static void OPC_6502_35 (void)
816/* Opcode $35: AND zp,x */
817{
818 AC_OP_ZPX (&);
819}
820
821
822
823static void OPC_6502_36 (void)
824/* Opcode $36: ROL zp,x */
825{
826 unsigned char ZPAddr;
827 unsigned Val;
828 Cycles = 6;
829 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
830 Val = MemReadByte (ZPAddr);
831 ROL (Val);
832 MemWriteByte (ZPAddr, Val);
833 Regs.PC += 2;
834}
835
836
837
838static void OPC_6502_38 (void)
839/* Opcode $38: SEC */
840{
841 Cycles = 2;
842 SET_CF (1);
843 Regs.PC += 1;
844}
845
846
847
848static void OPC_6502_39 (void)
849/* Opcode $39: AND abs,y */
850{
851 AC_OP_ABSY (&);
852}
853
854
855
856static void OPC_65SC02_3A (void)
857/* Opcode $3A: DEC a */
858{
859 Cycles = 2;
860 Regs.AC = (Regs.AC - 1) & 0xFF;
861 TEST_ZF (Regs.AC);
862 TEST_SF (Regs.AC);
863 Regs.PC += 1;
864}
865
866
867
868static void OPC_65SC02_3C (void)
869/* Opcode $3C: BIT abs,x */
870{
871 unsigned Addr;
872 unsigned char Val;
873 Cycles = 4;
874 Addr = MemReadWord (Regs.PC+1);
875 if (PAGE_CROSS (Addr, Regs.XR))
876 ++Cycles;
877 Val = MemReadByte (Addr + Regs.XR);
878 SET_SF (Val & 0x80);
879 SET_OF (Val & 0x40);
880 SET_ZF ((Val & Regs.AC) == 0);
881 Regs.PC += 3;
882}
883
884
885
886static void OPC_6502_3D (void)
887/* Opcode $3D: AND abs,x */
888{
889 AC_OP_ABSX (&);
890}
891
892
893
894static void OPC_6502_3E (void)
895/* Opcode $3E: ROL abs,x */
896{
897 unsigned Addr;
898 unsigned Val;
899 Cycles = 7;
900 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
901 if (CPU != CPU_6502 && !PAGE_CROSS (Addr, Regs.XR))
902 --Cycles;
903 Val = MemReadByte (Addr);
904 ROL (Val);
905 MemWriteByte (Addr, Val);
906 Regs.PC += 2;
907}
908
909
910
911static void OPC_6502_40 (void)
912/* Opcode $40: RTI */
913{
914 Cycles = 6;
915
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 */
920}
921
922
923
924static void OPC_6502_41 (void)
925/* Opcode $41: EOR (zp,x) */
926{
927 AC_OP_ZPXIND (^);
928}
929
930
931
932static void OPC_65C02_44 (void)
933/* Opcode $44: 'zp' 3 cycle NOP */
934{
935 Cycles = 3;
936 Regs.PC += 2;
937}
938
939
940
941static void OPC_6502_45 (void)
942/* Opcode $45: EOR zp */
943{
944 AC_OP_ZP (^);
945}
946
947
948
949static void OPC_6502_46 (void)
950/* Opcode $46: LSR zp */
951{
952 unsigned char ZPAddr;
953 unsigned char Val;
954 Cycles = 5;
955 ZPAddr = MemReadByte (Regs.PC+1);
956 Val = MemReadByte (ZPAddr);
957 SET_CF (Val & 0x01);
958 Val >>= 1;
959 MemWriteByte (ZPAddr, Val);
960 TEST_ZF (Val);
961 TEST_SF (Val);
962 Regs.PC += 2;
963}
964
965
966
967static void OPC_6502_48 (void)
968/* Opcode $48: PHA */
969{
970 Cycles = 3;
971 PUSH (Regs.AC);
972 Regs.PC += 1;
973}
974
975
976
977static void OPC_6502_49 (void)
978/* Opcode $49: EOR #imm */
979{
980 AC_OP_IMM (^);
981}
982
983
984
985static void OPC_6502_4A (void)
986/* Opcode $4A: LSR a */
987{
988 Cycles = 2;
989 SET_CF (Regs.AC & 0x01);
990 Regs.AC >>= 1;
991 TEST_ZF (Regs.AC);
992 TEST_SF (Regs.AC);
993 Regs.PC += 1;
994}
995
996
997
998static void OPC_6502_4C (void)
999/* Opcode $4C: JMP abs */
1000{
1001 Cycles = 3;
1002 Regs.PC = MemReadWord (Regs.PC+1);
1003
1004 ParaVirtHooks (&Regs);
1005}
1006
1007
1008
1009static void OPC_6502_4D (void)
1010/* Opcode $4D: EOR abs */
1011{
1012 AC_OP_ABS (^);
1013}
1014
1015
1016
1017static void OPC_6502_4E (void)
1018/* Opcode $4E: LSR abs */
1019{
1020 unsigned Addr;
1021 unsigned char Val;
1022 Cycles = 6;
1023 Addr = MemReadWord (Regs.PC+1);
1024 Val = MemReadByte (Addr);
1025 SET_CF (Val & 0x01);
1026 Val >>= 1;
1027 MemWriteByte (Addr, Val);
1028 TEST_ZF (Val);
1029 TEST_SF (Val);
1030 Regs.PC += 3;
1031}
1032
1033
1034
1035static void OPC_6502_50 (void)
1036/* Opcode $50: BVC */
1037{
1038 BRANCH (!GET_OF ());
1039}
1040
1041
1042
1043static void OPC_6502_51 (void)
1044/* Opcode $51: EOR (zp),y */
1045{
1046 AC_OP_ZPINDY (^);
1047}
1048
1049
1050
1051static void OPC_65SC02_52 (void)
1052/* Opcode $52: EOR (zp) */
1053{
1054 AC_OP_ZPIND (^);
1055}
1056
1057
1058
1059static void OPC_6502_55 (void)
1060/* Opcode $55: EOR zp,x */
1061{
1062 AC_OP_ZPX (^);
1063}
1064
1065
1066
1067static void OPC_6502_56 (void)
1068/* Opcode $56: LSR zp,x */
1069{
1070 unsigned char ZPAddr;
1071 unsigned char Val;
1072 Cycles = 6;
1073 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1074 Val = MemReadByte (ZPAddr);
1075 SET_CF (Val & 0x01);
1076 Val >>= 1;
1077 MemWriteByte (ZPAddr, Val);
1078 TEST_ZF (Val);
1079 TEST_SF (Val);
1080 Regs.PC += 2;
1081}
1082
1083
1084
1085static void OPC_6502_58 (void)
1086/* Opcode $58: CLI */
1087{
1088 Cycles = 2;
1089 SET_IF (0);
1090 Regs.PC += 1;
1091}
1092
1093
1094
1095static void OPC_6502_59 (void)
1096/* Opcode $59: EOR abs,y */
1097{
1098 AC_OP_ABSY (^);
1099}
1100
1101
1102
1103static void OPC_65SC02_5A (void)
1104/* Opcode $5A: PHY */
1105{
1106 Cycles = 3;
1107 PUSH (Regs.YR);
1108 Regs.PC += 1;
1109}
1110
1111
1112
1113static void OPC_65C02_5C (void)
1114/* Opcode $5C: 'Absolute' 8 cycle NOP */
1115{
1116 Cycles = 8;
1117 Regs.PC += 3;
1118}
1119
1120
1121
1122static void OPC_6502_5D (void)
1123/* Opcode $5D: EOR abs,x */
1124{
1125 AC_OP_ABSX (^);
1126}
1127
1128
1129
1130static void OPC_6502_5E (void)
1131/* Opcode $5E: LSR abs,x */
1132{
1133 unsigned Addr;
1134 unsigned char Val;
1135 Cycles = 7;
1136 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
1137 if (CPU != CPU_6502 && !PAGE_CROSS (Addr, Regs.XR))
1138 --Cycles;
1139 Val = MemReadByte (Addr);
1140 SET_CF (Val & 0x01);
1141 Val >>= 1;
1142 MemWriteByte (Addr, Val);
1143 TEST_ZF (Val);
1144 TEST_SF (Val);
1145 Regs.PC += 3;
1146}
1147
1148
1149
1150static void OPC_6502_60 (void)
1151/* Opcode $60: RTS */
1152{
1153 Cycles = 6;
1154 Regs.PC = POP (); /* PCL */
1155 Regs.PC |= (POP () << 8); /* PCH */
1156 Regs.PC += 1;
1157}
1158
1159
1160
1161static void OPC_6502_61 (void)
1162/* Opcode $61: ADC (zp,x) */
1163{
1164 unsigned char ZPAddr;
1165 unsigned Addr;
1166 Cycles = 6;
1167 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1168 Addr = MemReadZPWord (ZPAddr);
1169 ADC (MemReadByte (Addr));
1170 Regs.PC += 2;
1171}
1172
1173
1174
1175static void OPC_65SC02_64 (void)
1176/* Opcode $64: STZ zp */
1177{
1178 unsigned char ZPAddr;
1179 Cycles = 3;
1180 ZPAddr = MemReadByte (Regs.PC+1);
1181 MemWriteByte (ZPAddr, 0);
1182 Regs.PC += 2;
1183}
1184
1185
1186
1187static void OPC_6502_65 (void)
1188/* Opcode $65: ADC zp */
1189{
1190 unsigned char ZPAddr;
1191 Cycles = 3;
1192 ZPAddr = MemReadByte (Regs.PC+1);
1193 ADC (MemReadByte (ZPAddr));
1194 Regs.PC += 2;
1195}
1196
1197
1198
1199static void OPC_6502_66 (void)
1200/* Opcode $66: ROR zp */
1201{
1202 unsigned char ZPAddr;
1203 unsigned Val;
1204 Cycles = 5;
1205 ZPAddr = MemReadByte (Regs.PC+1);
1206 Val = MemReadByte (ZPAddr);
1207 ROR (Val);
1208 MemWriteByte (ZPAddr, Val);
1209 Regs.PC += 2;
1210}
1211
1212
1213
1214static void OPC_6502_68 (void)
1215/* Opcode $68: PLA */
1216{
1217 Cycles = 4;
1218 Regs.AC = POP ();
1219 TEST_ZF (Regs.AC);
1220 TEST_SF (Regs.AC);
1221 Regs.PC += 1;
1222}
1223
1224
1225
1226static void OPC_6502_69 (void)
1227/* Opcode $69: ADC #imm */
1228{
1229 Cycles = 2;
1230 ADC (MemReadByte (Regs.PC+1));
1231 Regs.PC += 2;
1232}
1233
1234
1235
1236static void OPC_6502_6A (void)
1237/* Opcode $6A: ROR a */
1238{
1239 Cycles = 2;
1240 ROR (Regs.AC);
1241 Regs.PC += 1;
1242}
1243
1244
1245
1246static void OPC_6502_6C (void)
1247/* Opcode $6C: JMP (ind) */
1248{
1249 unsigned PC, Lo, Hi;
1250 PC = Regs.PC;
1251 Lo = MemReadWord (PC+1);
1252
1253 if (CPU == CPU_6502)
1254 {
1255 /* Emulate the 6502 bug */
1256 Cycles = 5;
1257 Regs.PC = MemReadByte (Lo);
1258 Hi = (Lo & 0xFF00) | ((Lo + 1) & 0xFF);
1259 Regs.PC |= (MemReadByte (Hi) << 8);
1260
1261 /* Output a warning if the bug is triggered */
1262 if (Hi != Lo + 1)
1263 {
1264 Warning ("6502 indirect jump bug triggered at $%04X, ind addr = $%04X",
1265 PC, Lo);
1266 }
1267 }
1268 else
1269 {
1270 Cycles = 6;
1271 Regs.PC = MemReadWord(Lo);
1272 }
1273
1274 ParaVirtHooks (&Regs);
1275}
1276
1277
1278
1279static void OPC_65C02_6C (void)
1280/* Opcode $6C: JMP (ind) */
1281{
1282 /* 6502 bug fixed here */
1283 Cycles = 5;
1284 Regs.PC = MemReadWord (MemReadWord (Regs.PC+1));
1285
1286 ParaVirtHooks (&Regs);
1287}
1288
1289
1290
1291static void OPC_6502_6D (void)
1292/* Opcode $6D: ADC abs */
1293{
1294 unsigned Addr;
1295 Cycles = 4;
1296 Addr = MemReadWord (Regs.PC+1);
1297 ADC (MemReadByte (Addr));
1298 Regs.PC += 3;
1299}
1300
1301
1302
1303static void OPC_6502_6E (void)
1304/* Opcode $6E: ROR abs */
1305{
1306 unsigned Addr;
1307 unsigned Val;
1308 Cycles = 6;
1309 Addr = MemReadWord (Regs.PC+1);
1310 Val = MemReadByte (Addr);
1311 ROR (Val);
1312 MemWriteByte (Addr, Val);
1313 Regs.PC += 3;
1314}
1315
1316
1317
1318static void OPC_6502_70 (void)
1319/* Opcode $70: BVS */
1320{
1321 BRANCH (GET_OF ());
1322}
1323
1324
1325
1326static void OPC_6502_71 (void)
1327/* Opcode $71: ADC (zp),y */
1328{
1329 unsigned char ZPAddr;
1330 unsigned Addr;
1331 Cycles = 5;
1332 ZPAddr = MemReadByte (Regs.PC+1);
1333 Addr = MemReadZPWord (ZPAddr);
1334 if (PAGE_CROSS (Addr, Regs.YR)) {
1335 ++Cycles;
1336 }
1337 ADC (MemReadByte (Addr + Regs.YR));
1338 Regs.PC += 2;
1339}
1340
1341
1342
1343static void OPC_65SC02_72 (void)
1344/* Opcode $72: ADC (zp) */
1345{
1346 unsigned char ZPAddr;
1347 unsigned Addr;
1348 Cycles = 5;
1349 ZPAddr = MemReadByte (Regs.PC+1);
1350 Addr = MemReadZPWord (ZPAddr);
1351 ADC (MemReadByte (Addr));
1352 Regs.PC += 2;
1353}
1354
1355
1356
1357static void OPC_65SC02_74 (void)
1358/* Opcode $74: STZ zp,x */
1359{
1360 unsigned char ZPAddr;
1361 Cycles = 4;
1362 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1363 MemWriteByte (ZPAddr, 0);
1364 Regs.PC += 2;
1365}
1366
1367
1368
1369static void OPC_6502_75 (void)
1370/* Opcode $75: ADC zp,x */
1371{
1372 unsigned char ZPAddr;
1373 Cycles = 4;
1374 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1375 ADC (MemReadByte (ZPAddr));
1376 Regs.PC += 2;
1377}
1378
1379
1380
1381static void OPC_6502_76 (void)
1382/* Opcode $76: ROR zp,x */
1383{
1384 unsigned char ZPAddr;
1385 unsigned Val;
1386 Cycles = 6;
1387 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1388 Val = MemReadByte (ZPAddr);
1389 ROR (Val);
1390 MemWriteByte (ZPAddr, Val);
1391 Regs.PC += 2;
1392}
1393
1394
1395
1396static void OPC_6502_78 (void)
1397/* Opcode $78: SEI */
1398{
1399 Cycles = 2;
1400 SET_IF (1);
1401 Regs.PC += 1;
1402}
1403
1404
1405
1406static void OPC_6502_79 (void)
1407/* Opcode $79: ADC abs,y */
1408{
1409 unsigned Addr;
1410 Cycles = 4;
1411 Addr = MemReadWord (Regs.PC+1);
1412 if (PAGE_CROSS (Addr, Regs.YR)) {
1413 ++Cycles;
1414 }
1415 ADC (MemReadByte (Addr + Regs.YR));
1416 Regs.PC += 3;
1417}
1418
1419
1420
1421static void OPC_65SC02_7A (void)
1422/* Opcode $7A: PLY */
1423{
1424 Cycles = 4;
1425 Regs.YR = POP ();
1426 TEST_ZF (Regs.YR);
1427 TEST_SF (Regs.YR);
1428 Regs.PC += 1;
1429}
1430
1431
1432
1433static void OPC_65SC02_7C (void)
1434/* Opcode $7C: JMP (ind,X) */
1435{
1436 unsigned PC, Adr;
1437 Cycles = 6;
1438 PC = Regs.PC;
1439 Adr = MemReadWord (PC+1);
1440 Regs.PC = MemReadWord(Adr+Regs.XR);
1441
1442 ParaVirtHooks (&Regs);
1443}
1444
1445
1446
1447static void OPC_6502_7D (void)
1448/* Opcode $7D: ADC abs,x */
1449{
1450 unsigned Addr;
1451 Cycles = 4;
1452 Addr = MemReadWord (Regs.PC+1);
1453 if (PAGE_CROSS (Addr, Regs.XR)) {
1454 ++Cycles;
1455 }
1456 ADC (MemReadByte (Addr + Regs.XR));
1457 Regs.PC += 3;
1458}
1459
1460
1461
1462static void OPC_6502_7E (void)
1463/* Opcode $7E: ROR abs,x */
1464{
1465 unsigned Addr;
1466 unsigned Val;
1467 Cycles = 7;
1468 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
1469 if (CPU != CPU_6502 && !PAGE_CROSS (Addr, Regs.XR))
1470 --Cycles;
1471 Val = MemReadByte (Addr);
1472 ROR (Val);
1473 MemWriteByte (Addr, Val);
1474 Regs.PC += 3;
1475}
1476
1477
1478
1479static void OPC_65SC02_80 (void)
1480/* Opcode $80: BRA */
1481{
1482 BRANCH (1);
1483}
1484
1485
1486
1487static void OPC_6502_81 (void)
1488/* Opcode $81: STA (zp,x) */
1489{
1490 unsigned char ZPAddr;
1491 unsigned Addr;
1492 Cycles = 6;
1493 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1494 Addr = MemReadZPWord (ZPAddr);
1495 MemWriteByte (Addr, Regs.AC);
1496 Regs.PC += 2;
1497}
1498
1499
1500
1501static void OPC_6502_84 (void)
1502/* Opcode $84: STY zp */
1503{
1504 unsigned char ZPAddr;
1505 Cycles = 3;
1506 ZPAddr = MemReadByte (Regs.PC+1);
1507 MemWriteByte (ZPAddr, Regs.YR);
1508 Regs.PC += 2;
1509}
1510
1511
1512
1513static void OPC_6502_85 (void)
1514/* Opcode $85: STA zp */
1515{
1516 unsigned char ZPAddr;
1517 Cycles = 3;
1518 ZPAddr = MemReadByte (Regs.PC+1);
1519 MemWriteByte (ZPAddr, Regs.AC);
1520 Regs.PC += 2;
1521}
1522
1523
1524
1525static void OPC_6502_86 (void)
1526/* Opcode $86: STX zp */
1527{
1528 unsigned char ZPAddr;
1529 Cycles = 3;
1530 ZPAddr = MemReadByte (Regs.PC+1);
1531 MemWriteByte (ZPAddr, Regs.XR);
1532 Regs.PC += 2;
1533}
1534
1535
1536
1537static void OPC_6502_88 (void)
1538/* Opcode $88: DEY */
1539{
1540 Cycles = 2;
1541 Regs.YR = (Regs.YR - 1) & 0xFF;
1542 TEST_ZF (Regs.YR);
1543 TEST_SF (Regs.YR);
1544 Regs.PC += 1;
1545}
1546
1547
1548
1549static void OPC_65SC02_89 (void)
1550/* Opcode $89: BIT #imm */
1551{
1552 unsigned char Val;
1553 Cycles = 2;
1554 Val = MemReadByte (Regs.PC+1);
1555 SET_SF (Val & 0x80);
1556 SET_OF (Val & 0x40);
1557 SET_ZF ((Val & Regs.AC) == 0);
1558 Regs.PC += 2;
1559}
1560
1561
1562
1563static void OPC_6502_8A (void)
1564/* Opcode $8A: TXA */
1565{
1566 Cycles = 2;
1567 Regs.AC = Regs.XR;
1568 TEST_ZF (Regs.AC);
1569 TEST_SF (Regs.AC);
1570 Regs.PC += 1;
1571}
1572
1573
1574
1575static void OPC_6502_8C (void)
1576/* Opcode $8C: STY abs */
1577{
1578 unsigned Addr;
1579 Cycles = 4;
1580 Addr = MemReadWord (Regs.PC+1);
1581 MemWriteByte (Addr, Regs.YR);
1582 Regs.PC += 3;
1583}
1584
1585
1586
1587static void OPC_6502_8D (void)
1588/* Opcode $8D: STA abs */
1589{
1590 unsigned Addr;
1591 Cycles = 4;
1592 Addr = MemReadWord (Regs.PC+1);
1593 MemWriteByte (Addr, Regs.AC);
1594 Regs.PC += 3;
1595}
1596
1597
1598
1599static void OPC_6502_8E (void)
1600/* Opcode $8E: STX abs */
1601{
1602 unsigned Addr;
1603 Cycles = 4;
1604 Addr = MemReadWord (Regs.PC+1);
1605 MemWriteByte (Addr, Regs.XR);
1606 Regs.PC += 3;
1607}
1608
1609
1610
1611static void OPC_6502_90 (void)
1612/* Opcode $90: BCC */
1613{
1614 BRANCH (!GET_CF ());
1615}
1616
1617
1618
1619static void OPC_6502_91 (void)
1620/* Opcode $91: sta (zp),y */
1621{
1622 unsigned char ZPAddr;
1623 unsigned Addr;
1624 Cycles = 6;
1625 ZPAddr = MemReadByte (Regs.PC+1);
1626 Addr = MemReadZPWord (ZPAddr) + Regs.YR;
1627 MemWriteByte (Addr, Regs.AC);
1628 Regs.PC += 2;
1629}
1630
1631
1632
1633static void OPC_65SC02_92 (void)
1634/* Opcode $92: sta (zp) */
1635{
1636 unsigned char ZPAddr;
1637 unsigned Addr;
1638 Cycles = 5;
1639 ZPAddr = MemReadByte (Regs.PC+1);
1640 Addr = MemReadZPWord (ZPAddr);
1641 MemWriteByte (Addr, Regs.AC);
1642 Regs.PC += 2;
1643}
1644
1645
1646
1647static void OPC_6502_94 (void)
1648/* Opcode $94: STY zp,x */
1649{
1650 unsigned char ZPAddr;
1651 Cycles = 4;
1652 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1653 MemWriteByte (ZPAddr, Regs.YR);
1654 Regs.PC += 2;
1655}
1656
1657
1658
1659static void OPC_6502_95 (void)
1660/* Opcode $95: STA zp,x */
1661{
1662 unsigned char ZPAddr;
1663 Cycles = 4;
1664 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1665 MemWriteByte (ZPAddr, Regs.AC);
1666 Regs.PC += 2;
1667}
1668
1669
1670
1671static void OPC_6502_96 (void)
1672/* Opcode $96: stx zp,y */
1673{
1674 unsigned char ZPAddr;
1675 Cycles = 4;
1676 ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR;
1677 MemWriteByte (ZPAddr, Regs.XR);
1678 Regs.PC += 2;
1679}
1680
1681
1682
1683static void OPC_6502_98 (void)
1684/* Opcode $98: TYA */
1685{
1686 Cycles = 2;
1687 Regs.AC = Regs.YR;
1688 TEST_ZF (Regs.AC);
1689 TEST_SF (Regs.AC);
1690 Regs.PC += 1;
1691}
1692
1693
1694
1695static void OPC_6502_99 (void)
1696/* Opcode $99: STA abs,y */
1697{
1698 unsigned Addr;
1699 Cycles = 5;
1700 Addr = MemReadWord (Regs.PC+1) + Regs.YR;
1701 MemWriteByte (Addr, Regs.AC);
1702 Regs.PC += 3;
1703}
1704
1705
1706
1707static void OPC_6502_9A (void)
1708/* Opcode $9A: TXS */
1709{
1710 Cycles = 2;
1711 Regs.SP = Regs.XR;
1712 Regs.PC += 1;
1713}
1714
1715
1716
1717static void OPC_65SC02_9C (void)
1718/* Opcode $9C: STZ abs */
1719{
1720 unsigned Addr;
1721 Cycles = 4;
1722 Addr = MemReadWord (Regs.PC+1);
1723 MemWriteByte (Addr, 0);
1724 Regs.PC += 3;
1725}
1726
1727
1728
1729static void OPC_6502_9D (void)
1730/* Opcode $9D: STA abs,x */
1731{
1732 unsigned Addr;
1733 Cycles = 5;
1734 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
1735 MemWriteByte (Addr, Regs.AC);
1736 Regs.PC += 3;
1737}
1738
1739
1740
1741static void OPC_65SC02_9E (void)
1742/* Opcode $9E: STZ abs,x */
1743{
1744 unsigned Addr;
1745 Cycles = 5;
1746 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
1747 MemWriteByte (Addr, 0);
1748 Regs.PC += 3;
1749}
1750
1751
1752
1753static void OPC_6502_A0 (void)
1754/* Opcode $A0: LDY #imm */
1755{
1756 Cycles = 2;
1757 Regs.YR = MemReadByte (Regs.PC+1);
1758 TEST_ZF (Regs.YR);
1759 TEST_SF (Regs.YR);
1760 Regs.PC += 2;
1761}
1762
1763
1764
1765static void OPC_6502_A1 (void)
1766/* Opcode $A1: LDA (zp,x) */
1767{
1768 unsigned char ZPAddr;
1769 unsigned Addr;
1770 Cycles = 6;
1771 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1772 Addr = MemReadZPWord (ZPAddr);
1773 Regs.AC = MemReadByte (Addr);
1774 TEST_ZF (Regs.AC);
1775 TEST_SF (Regs.AC);
1776 Regs.PC += 2;
1777}
1778
1779
1780
1781static void OPC_6502_A2 (void)
1782/* Opcode $A2: LDX #imm */
1783{
1784 Cycles = 2;
1785 Regs.XR = MemReadByte (Regs.PC+1);
1786 TEST_ZF (Regs.XR);
1787 TEST_SF (Regs.XR);
1788 Regs.PC += 2;
1789}
1790
1791
1792
1793static void OPC_6502_A4 (void)
1794/* Opcode $A4: LDY zp */
1795{
1796 unsigned char ZPAddr;
1797 Cycles = 3;
1798 ZPAddr = MemReadByte (Regs.PC+1);
1799 Regs.YR = MemReadByte (ZPAddr);
1800 TEST_ZF (Regs.YR);
1801 TEST_SF (Regs.YR);
1802 Regs.PC += 2;
1803}
1804
1805
1806
1807static void OPC_6502_A5 (void)
1808/* Opcode $A5: LDA zp */
1809{
1810 unsigned char ZPAddr;
1811 Cycles = 3;
1812 ZPAddr = MemReadByte (Regs.PC+1);
1813 Regs.AC = MemReadByte (ZPAddr);
1814 TEST_ZF (Regs.AC);
1815 TEST_SF (Regs.AC);
1816 Regs.PC += 2;
1817}
1818
1819
1820
1821static void OPC_6502_A6 (void)
1822/* Opcode $A6: LDX zp */
1823{
1824 unsigned char ZPAddr;
1825 Cycles = 3;
1826 ZPAddr = MemReadByte (Regs.PC+1);
1827 Regs.XR = MemReadByte (ZPAddr);
1828 TEST_ZF (Regs.XR);
1829 TEST_SF (Regs.XR);
1830 Regs.PC += 2;
1831}
1832
1833
1834
1835static void OPC_6502_A8 (void)
1836/* Opcode $A8: TAY */
1837{
1838 Cycles = 2;
1839 Regs.YR = Regs.AC;
1840 TEST_ZF (Regs.YR);
1841 TEST_SF (Regs.YR);
1842 Regs.PC += 1;
1843}
1844
1845
1846
1847static void OPC_6502_A9 (void)
1848/* Opcode $A9: LDA #imm */
1849{
1850 Cycles = 2;
1851 Regs.AC = MemReadByte (Regs.PC+1);
1852 TEST_ZF (Regs.AC);
1853 TEST_SF (Regs.AC);
1854 Regs.PC += 2;
1855}
1856
1857
1858
1859static void OPC_6502_AA (void)
1860/* Opcode $AA: TAX */
1861{
1862 Cycles = 2;
1863 Regs.XR = Regs.AC;
1864 TEST_ZF (Regs.XR);
1865 TEST_SF (Regs.XR);
1866 Regs.PC += 1;
1867}
1868
1869
1870
1871static void OPC_6502_AC (void)
1872/* Opcode $Regs.AC: LDY abs */
1873{
1874 unsigned Addr;
1875 Cycles = 4;
1876 Addr = MemReadWord (Regs.PC+1);
1877 Regs.YR = MemReadByte (Addr);
1878 TEST_ZF (Regs.YR);
1879 TEST_SF (Regs.YR);
1880 Regs.PC += 3;
1881}
1882
1883
1884
1885static void OPC_6502_AD (void)
1886/* Opcode $AD: LDA abs */
1887{
1888 unsigned Addr;
1889 Cycles = 4;
1890 Addr = MemReadWord (Regs.PC+1);
1891 Regs.AC = MemReadByte (Addr);
1892 TEST_ZF (Regs.AC);
1893 TEST_SF (Regs.AC);
1894 Regs.PC += 3;
1895}
1896
1897
1898
1899static void OPC_6502_AE (void)
1900/* Opcode $AE: LDX abs */
1901{
1902 unsigned Addr;
1903 Cycles = 4;
1904 Addr = MemReadWord (Regs.PC+1);
1905 Regs.XR = MemReadByte (Addr);
1906 TEST_ZF (Regs.XR);
1907 TEST_SF (Regs.XR);
1908 Regs.PC += 3;
1909}
1910
1911
1912
1913static void OPC_6502_B0 (void)
1914/* Opcode $B0: BCS */
1915{
1916 BRANCH (GET_CF ());
1917}
1918
1919
1920
1921static void OPC_6502_B1 (void)
1922/* Opcode $B1: LDA (zp),y */
1923{
1924 unsigned char ZPAddr;
1925 unsigned Addr;
1926 Cycles = 5;
1927 ZPAddr = MemReadByte (Regs.PC+1);
1928 Addr = MemReadZPWord (ZPAddr);
1929 if (PAGE_CROSS (Addr, Regs.YR)) {
1930 ++Cycles;
1931 }
1932 Regs.AC = MemReadByte (Addr + Regs.YR);
1933 TEST_ZF (Regs.AC);
1934 TEST_SF (Regs.AC);
1935 Regs.PC += 2;
1936}
1937
1938
1939
1940static void OPC_65SC02_B2 (void)
1941/* Opcode $B2: LDA (zp) */
1942{
1943 unsigned char ZPAddr;
1944 unsigned Addr;
1945 Cycles = 5;
1946 ZPAddr = MemReadByte (Regs.PC+1);
1947 Addr = MemReadZPWord (ZPAddr);
1948 Regs.AC = MemReadByte (Addr);
1949 TEST_ZF (Regs.AC);
1950 TEST_SF (Regs.AC);
1951 Regs.PC += 2;
1952}
1953
1954
1955
1956static void OPC_6502_B4 (void)
1957/* Opcode $B4: LDY zp,x */
1958{
1959 unsigned char ZPAddr;
1960 Cycles = 4;
1961 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1962 Regs.YR = MemReadByte (ZPAddr);
1963 TEST_ZF (Regs.YR);
1964 TEST_SF (Regs.YR);
1965 Regs.PC += 2;
1966}
1967
1968
1969
1970static void OPC_6502_B5 (void)
1971/* Opcode $B5: LDA zp,x */
1972{
1973 unsigned char ZPAddr;
1974 Cycles = 4;
1975 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
1976 Regs.AC = MemReadByte (ZPAddr);
1977 TEST_ZF (Regs.AC);
1978 TEST_SF (Regs.AC);
1979 Regs.PC += 2;
1980}
1981
1982
1983
1984static void OPC_6502_B6 (void)
1985/* Opcode $B6: LDX zp,y */
1986{
1987 unsigned char ZPAddr;
1988 Cycles = 4;
1989 ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR;
1990 Regs.XR = MemReadByte (ZPAddr);
1991 TEST_ZF (Regs.XR);
1992 TEST_SF (Regs.XR);
1993 Regs.PC += 2;
1994}
1995
1996
1997
1998static void OPC_6502_B8 (void)
1999/* Opcode $B8: CLV */
2000{
2001 Cycles = 2;
2002 SET_OF (0);
2003 Regs.PC += 1;
2004}
2005
2006
2007
2008static void OPC_6502_B9 (void)
2009/* Opcode $B9: LDA abs,y */
2010{
2011 unsigned Addr;
2012 Cycles = 4;
2013 Addr = MemReadWord (Regs.PC+1);
2014 if (PAGE_CROSS (Addr, Regs.YR)) {
2015 ++Cycles;
2016 }
2017 Regs.AC = MemReadByte (Addr + Regs.YR);
2018 TEST_ZF (Regs.AC);
2019 TEST_SF (Regs.AC);
2020 Regs.PC += 3;
2021}
2022
2023
2024
2025static void OPC_6502_BA (void)
2026/* Opcode $BA: TSX */
2027{
2028 Cycles = 2;
2029 Regs.XR = Regs.SP & 0xFF;
2030 TEST_ZF (Regs.XR);
2031 TEST_SF (Regs.XR);
2032 Regs.PC += 1;
2033}
2034
2035
2036
2037static void OPC_6502_BC (void)
2038/* Opcode $BC: LDY abs,x */
2039{
2040 unsigned Addr;
2041 Cycles = 4;
2042 Addr = MemReadWord (Regs.PC+1);
2043 if (PAGE_CROSS (Addr, Regs.XR)) {
2044 ++Cycles;
2045 }
2046 Regs.YR = MemReadByte (Addr + Regs.XR);
2047 TEST_ZF (Regs.YR);
2048 TEST_SF (Regs.YR);
2049 Regs.PC += 3;
2050}
2051
2052
2053
2054static void OPC_6502_BD (void)
2055/* Opcode $BD: LDA abs,x */
2056{
2057 unsigned Addr;
2058 Cycles = 4;
2059 Addr = MemReadWord (Regs.PC+1);
2060 if (PAGE_CROSS (Addr, Regs.XR)) {
2061 ++Cycles;
2062 }
2063 Regs.AC = MemReadByte (Addr + Regs.XR);
2064 TEST_ZF (Regs.AC);
2065 TEST_SF (Regs.AC);
2066 Regs.PC += 3;
2067}
2068
2069
2070
2071static void OPC_6502_BE (void)
2072/* Opcode $BE: LDX abs,y */
2073{
2074 unsigned Addr;
2075 Cycles = 4;
2076 Addr = MemReadWord (Regs.PC+1);
2077 if (PAGE_CROSS (Addr, Regs.YR)) {
2078 ++Cycles;
2079 }
2080 Regs.XR = MemReadByte (Addr + Regs.YR);
2081 TEST_ZF (Regs.XR);
2082 TEST_SF (Regs.XR);
2083 Regs.PC += 3;
2084}
2085
2086
2087
2088static void OPC_6502_C0 (void)
2089/* Opcode $C0: CPY #imm */
2090{
2091 Cycles = 2;
2092 CMP (Regs.YR, MemReadByte (Regs.PC+1));
2093 Regs.PC += 2;
2094}
2095
2096
2097
2098static void OPC_6502_C1 (void)
2099/* Opcode $C1: CMP (zp,x) */
2100{
2101 unsigned char ZPAddr;
2102 unsigned Addr;
2103 Cycles = 6;
2104 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
2105 Addr = MemReadZPWord (ZPAddr);
2106 CMP (Regs.AC, MemReadByte (Addr));
2107 Regs.PC += 2;
2108}
2109
2110
2111
2112static void OPC_6502_C4 (void)
2113/* Opcode $C4: CPY zp */
2114{
2115 unsigned char ZPAddr;
2116 Cycles = 3;
2117 ZPAddr = MemReadByte (Regs.PC+1);
2118 CMP (Regs.YR, MemReadByte (ZPAddr));
2119 Regs.PC += 2;
2120}
2121
2122
2123
2124static void OPC_6502_C5 (void)
2125/* Opcode $C5: CMP zp */
2126{
2127 unsigned char ZPAddr;
2128 Cycles = 3;
2129 ZPAddr = MemReadByte (Regs.PC+1);
2130 CMP (Regs.AC, MemReadByte (ZPAddr));
2131 Regs.PC += 2;
2132}
2133
2134
2135
2136static void OPC_6502_C6 (void)
2137/* Opcode $C6: DEC zp */
2138{
2139 unsigned char ZPAddr;
2140 unsigned char Val;
2141 Cycles = 5;
2142 ZPAddr = MemReadByte (Regs.PC+1);
2143 Val = MemReadByte (ZPAddr) - 1;
2144 MemWriteByte (ZPAddr, Val);
2145 TEST_ZF (Val);
2146 TEST_SF (Val);
2147 Regs.PC += 2;
2148}
2149
2150
2151
2152static void OPC_6502_C8 (void)
2153/* Opcode $C8: INY */
2154{
2155 Cycles = 2;
2156 Regs.YR = (Regs.YR + 1) & 0xFF;
2157 TEST_ZF (Regs.YR);
2158 TEST_SF (Regs.YR);
2159 Regs.PC += 1;
2160}
2161
2162
2163
2164static void OPC_6502_C9 (void)
2165/* Opcode $C9: CMP #imm */
2166{
2167 Cycles = 2;
2168 CMP (Regs.AC, MemReadByte (Regs.PC+1));
2169 Regs.PC += 2;
2170}
2171
2172
2173
2174static void OPC_6502_CA (void)
2175/* Opcode $CA: DEX */
2176{
2177 Cycles = 2;
2178 Regs.XR = (Regs.XR - 1) & 0xFF;
2179 TEST_ZF (Regs.XR);
2180 TEST_SF (Regs.XR);
2181 Regs.PC += 1;
2182}
2183
2184
2185
2186static void OPC_6502_CC (void)
2187/* Opcode $CC: CPY abs */
2188{
2189 unsigned Addr;
2190 Cycles = 4;
2191 Addr = MemReadWord (Regs.PC+1);
2192 CMP (Regs.YR, MemReadByte (Addr));
2193 Regs.PC += 3;
2194}
2195
2196
2197
2198static void OPC_6502_CD (void)
2199/* Opcode $CD: CMP abs */
2200{
2201 unsigned Addr;
2202 Cycles = 4;
2203 Addr = MemReadWord (Regs.PC+1);
2204 CMP (Regs.AC, MemReadByte (Addr));
2205 Regs.PC += 3;
2206}
2207
2208
2209
2210static void OPC_6502_CE (void)
2211/* Opcode $CE: DEC abs */
2212{
2213 unsigned Addr;
2214 unsigned char Val;
2215 Cycles = 6;
2216 Addr = MemReadWord (Regs.PC+1);
2217 Val = MemReadByte (Addr) - 1;
2218 MemWriteByte (Addr, Val);
2219 TEST_ZF (Val);
2220 TEST_SF (Val);
2221 Regs.PC += 3;
2222}
2223
2224
2225
2226static void OPC_6502_D0 (void)
2227/* Opcode $D0: BNE */
2228{
2229 BRANCH (!GET_ZF ());
2230}
2231
2232
2233
2234static void OPC_6502_D1 (void)
2235/* Opcode $D1: CMP (zp),y */
2236{
2237 unsigned ZPAddr;
2238 unsigned Addr;
2239 Cycles = 5;
2240 ZPAddr = MemReadByte (Regs.PC+1);
2241 Addr = MemReadWord (ZPAddr);
2242 if (PAGE_CROSS (Addr, Regs.YR)) {
2243 ++Cycles;
2244 }
2245 CMP (Regs.AC, MemReadByte (Addr + Regs.YR));
2246 Regs.PC += 2;
2247}
2248
2249
2250
2251static void OPC_65SC02_D2 (void)
2252/* Opcode $D2: CMP (zp) */
2253{
2254 unsigned ZPAddr;
2255 unsigned Addr;
2256 Cycles = 5;
2257 ZPAddr = MemReadByte (Regs.PC+1);
2258 Addr = MemReadWord (ZPAddr);
2259 CMP (Regs.AC, MemReadByte (Addr));
2260 Regs.PC += 2;
2261}
2262
2263
2264
2265static void OPC_6502_D5 (void)
2266/* Opcode $D5: CMP zp,x */
2267{
2268 unsigned char ZPAddr;
2269 Cycles = 4;
2270 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
2271 CMP (Regs.AC, MemReadByte (ZPAddr));
2272 Regs.PC += 2;
2273}
2274
2275
2276
2277static void OPC_6502_D6 (void)
2278/* Opcode $D6: DEC zp,x */
2279{
2280 unsigned char ZPAddr;
2281 unsigned char Val;
2282 Cycles = 6;
2283 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
2284 Val = MemReadByte (ZPAddr) - 1;
2285 MemWriteByte (ZPAddr, Val);
2286 TEST_ZF (Val);
2287 TEST_SF (Val);
2288 Regs.PC += 2;
2289}
2290
2291
2292
2293static void OPC_6502_D8 (void)
2294/* Opcode $D8: CLD */
2295{
2296 Cycles = 2;
2297 SET_DF (0);
2298 Regs.PC += 1;
2299}
2300
2301
2302
2303static void OPC_6502_D9 (void)
2304/* Opcode $D9: CMP abs,y */
2305{
2306 unsigned Addr;
2307 Cycles = 4;
2308 Addr = MemReadWord (Regs.PC+1);
2309 if (PAGE_CROSS (Addr, Regs.YR)) {
2310 ++Cycles;
2311 }
2312 CMP (Regs.AC, MemReadByte (Addr + Regs.YR));
2313 Regs.PC += 3;
2314}
2315
2316
2317
2318static void OPC_65SC02_DA (void)
2319/* Opcode $DA: PHX */
2320{
2321 Cycles = 3;
2322 PUSH (Regs.XR);
2323 Regs.PC += 1;
2324}
2325
2326
2327
2328static void OPC_6502_DD (void)
2329/* Opcode $DD: CMP abs,x */
2330{
2331 unsigned Addr;
2332 Cycles = 4;
2333 Addr = MemReadWord (Regs.PC+1);
2334 if (PAGE_CROSS (Addr, Regs.XR)) {
2335 ++Cycles;
2336 }
2337 CMP (Regs.AC, MemReadByte (Addr + Regs.XR));
2338 Regs.PC += 3;
2339}
2340
2341
2342
2343static void OPC_6502_DE (void)
2344/* Opcode $DE: DEC abs,x */
2345{
2346 unsigned Addr;
2347 unsigned char Val;
2348 Cycles = 7;
2349 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
2350 Val = MemReadByte (Addr) - 1;
2351 MemWriteByte (Addr, Val);
2352 TEST_ZF (Val);
2353 TEST_SF (Val);
2354 Regs.PC += 3;
2355}
2356
2357
2358
2359static void OPC_6502_E0 (void)
2360/* Opcode $E0: CPX #imm */
2361{
2362 Cycles = 2;
2363 CMP (Regs.XR, MemReadByte (Regs.PC+1));
2364 Regs.PC += 2;
2365}
2366
2367
2368
2369static void OPC_6502_E1 (void)
2370/* Opcode $E1: SBC (zp,x) */
2371{
2372 unsigned char ZPAddr;
2373 unsigned Addr;
2374 Cycles = 6;
2375 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
2376 Addr = MemReadZPWord (ZPAddr);
2377 SBC (MemReadByte (Addr));
2378 Regs.PC += 2;
2379}
2380
2381
2382
2383static void OPC_6502_E4 (void)
2384/* Opcode $E4: CPX zp */
2385{
2386 unsigned char ZPAddr;
2387 Cycles = 3;
2388 ZPAddr = MemReadByte (Regs.PC+1);
2389 CMP (Regs.XR, MemReadByte (ZPAddr));
2390 Regs.PC += 2;
2391}
2392
2393
2394
2395static void OPC_6502_E5 (void)
2396/* Opcode $E5: SBC zp */
2397{
2398 unsigned char ZPAddr;
2399 Cycles = 3;
2400 ZPAddr = MemReadByte (Regs.PC+1);
2401 SBC (MemReadByte (ZPAddr));
2402 Regs.PC += 2;
2403}
2404
2405
2406
2407static void OPC_6502_E6 (void)
2408/* Opcode $E6: INC zp */
2409{
2410 unsigned char ZPAddr;
2411 unsigned char Val;
2412 Cycles = 5;
2413 ZPAddr = MemReadByte (Regs.PC+1);
2414 Val = MemReadByte (ZPAddr) + 1;
2415 MemWriteByte (ZPAddr, Val);
2416 TEST_ZF (Val);
2417 TEST_SF (Val);
2418 Regs.PC += 2;
2419}
2420
2421
2422
2423static void OPC_6502_E8 (void)
2424/* Opcode $E8: INX */
2425{
2426 Cycles = 2;
2427 Regs.XR = (Regs.XR + 1) & 0xFF;
2428 TEST_ZF (Regs.XR);
2429 TEST_SF (Regs.XR);
2430 Regs.PC += 1;
2431}
2432
2433
2434
2435static void OPC_6502_E9 (void)
2436/* Opcode $E9: SBC #imm */
2437{
2438 Cycles = 2;
2439 SBC (MemReadByte (Regs.PC+1));
2440 Regs.PC += 2;
2441}
2442
2443
2444
2445static void OPC_6502_EA (void)
2446/* Opcode $EA: NOP */
2447{
2448 /* This one is easy... */
2449 Cycles = 2;
2450 Regs.PC += 1;
2451}
2452
2453
2454
2455static void OPC_65C02_NOP11(void)
2456/* Opcode 'Illegal' 1 cycle NOP */
2457{
2458 Cycles = 1;
2459 Regs.PC += 1;
2460}
2461
2462
2463
2464static void OPC_65C02_NOP22 (void)
2465/* Opcode 'Illegal' 2 byte 2 cycle NOP */
2466{
2467 Cycles = 2;
2468 Regs.PC += 2;
2469}
2470
2471
2472
2473static void OPC_65C02_NOP24 (void)
2474/* Opcode 'Illegal' 2 byte 4 cycle NOP */
2475{
2476 Cycles = 4;
2477 Regs.PC += 2;
2478}
2479
2480
2481
2482static void OPC_65C02_NOP34 (void)
2483/* Opcode 'Illegal' 3 byte 4 cycle NOP */
2484{
2485 Cycles = 4;
2486 Regs.PC += 3;
2487}
2488
2489
2490
2491static void OPC_6502_EC (void)
2492/* Opcode $EC: CPX abs */
2493{
2494 unsigned Addr;
2495 Cycles = 4;
2496 Addr = MemReadWord (Regs.PC+1);
2497 CMP (Regs.XR, MemReadByte (Addr));
2498 Regs.PC += 3;
2499}
2500
2501
2502
2503static void OPC_6502_ED (void)
2504/* Opcode $ED: SBC abs */
2505{
2506 unsigned Addr;
2507 Cycles = 4;
2508 Addr = MemReadWord (Regs.PC+1);
2509 SBC (MemReadByte (Addr));
2510 Regs.PC += 3;
2511}
2512
2513
2514
2515static void OPC_6502_EE (void)
2516/* Opcode $EE: INC abs */
2517{
2518 unsigned Addr;
2519 unsigned char Val;
2520 Cycles = 6;
2521 Addr = MemReadWord (Regs.PC+1);
2522 Val = MemReadByte (Addr) + 1;
2523 MemWriteByte (Addr, Val);
2524 TEST_ZF (Val);
2525 TEST_SF (Val);
2526 Regs.PC += 3;
2527}
2528
2529
2530
2531static void OPC_6502_F0 (void)
2532/* Opcode $F0: BEQ */
2533{
2534 BRANCH (GET_ZF ());
2535}
2536
2537
2538
2539static void OPC_6502_F1 (void)
2540/* Opcode $F1: SBC (zp),y */
2541{
2542 unsigned char ZPAddr;
2543 unsigned Addr;
2544 Cycles = 5;
2545 ZPAddr = MemReadByte (Regs.PC+1);
2546 Addr = MemReadZPWord (ZPAddr);
2547 if (PAGE_CROSS (Addr, Regs.YR)) {
2548 ++Cycles;
2549 }
2550 SBC (MemReadByte (Addr + Regs.YR));
2551 Regs.PC += 2;
2552}
2553
2554
2555
2556static void OPC_65SC02_F2 (void)
2557/* Opcode $F2: SBC (zp) */
2558{
2559 unsigned char ZPAddr;
2560 unsigned Addr;
2561 Cycles = 5;
2562 ZPAddr = MemReadByte (Regs.PC+1);
2563 Addr = MemReadZPWord (ZPAddr);
2564 SBC (MemReadByte (Addr));
2565 Regs.PC += 2;
2566}
2567
2568
2569
2570static void OPC_6502_F5 (void)
2571/* Opcode $F5: SBC zp,x */
2572{
2573 unsigned char ZPAddr;
2574 Cycles = 4;
2575 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
2576 SBC (MemReadByte (ZPAddr));
2577 Regs.PC += 2;
2578}
2579
2580
2581
2582static void OPC_6502_F6 (void)
2583/* Opcode $F6: INC zp,x */
2584{
2585 unsigned char ZPAddr;
2586 unsigned char Val;
2587 Cycles = 6;
2588 ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
2589 Val = MemReadByte (ZPAddr) + 1;
2590 MemWriteByte (ZPAddr, Val);
2591 TEST_ZF (Val);
2592 TEST_SF (Val);
2593 Regs.PC += 2;
2594}
2595
2596
2597
2598static void OPC_6502_F8 (void)
2599/* Opcode $F8: SED */
2600{
2601 Cycles = 2;
2602 SET_DF (1);
2603 Regs.PC += 1;
2604}
2605
2606
2607
2608static void OPC_6502_F9 (void)
2609/* Opcode $F9: SBC abs,y */
2610{
2611 unsigned Addr;
2612 Cycles = 4;
2613 Addr = MemReadWord (Regs.PC+1);
2614 if (PAGE_CROSS (Addr, Regs.YR)) {
2615 ++Cycles;
2616 }
2617 SBC (MemReadByte (Addr + Regs.YR));
2618 Regs.PC += 3;
2619}
2620
2621
2622
2623static void OPC_65SC02_FA (void)
2624/* Opcode $7A: PLX */
2625{
2626 Cycles = 4;
2627 Regs.XR = POP ();
2628 TEST_ZF (Regs.XR);
2629 TEST_SF (Regs.XR);
2630 Regs.PC += 1;
2631}
2632
2633
2634
2635static void OPC_6502_FD (void)
2636/* Opcode $FD: SBC abs,x */
2637{
2638 unsigned Addr;
2639 Cycles = 4;
2640 Addr = MemReadWord (Regs.PC+1);
2641 if (PAGE_CROSS (Addr, Regs.XR)) {
2642 ++Cycles;
2643 }
2644 SBC (MemReadByte (Addr + Regs.XR));
2645 Regs.PC += 3;
2646}
2647
2648
2649
2650static void OPC_6502_FE (void)
2651/* Opcode $FE: INC abs,x */
2652{
2653 unsigned Addr;
2654 unsigned char Val;
2655 Cycles = 7;
2656 Addr = MemReadWord (Regs.PC+1) + Regs.XR;
2657 Val = MemReadByte (Addr) + 1;
2658 MemWriteByte (Addr, Val);
2659 TEST_ZF (Val);
2660 TEST_SF (Val);
2661 Regs.PC += 3;
2662}
2663
2664
2665
2666/*****************************************************************************/
2667/* Opcode handler tables */
2668/*****************************************************************************/
2669
2670
2671
2672/* Opcode handler table for the 6502 */
2673static const OPFunc OP6502Table[256] = {
2674 OPC_6502_00,
2675 OPC_6502_01,
2676 OPC_Illegal,
2677 OPC_Illegal,
2678 OPC_Illegal,
2679 OPC_6502_05,
2680 OPC_6502_06,
2681 OPC_Illegal,
2682 OPC_6502_08,
2683 OPC_6502_09,
2684 OPC_6502_0A,
2685 OPC_Illegal,
2686 OPC_Illegal,
2687 OPC_6502_0D,
2688 OPC_6502_0E,
2689 OPC_Illegal,
2690 OPC_6502_10,
2691 OPC_6502_11,
2692 OPC_Illegal,
2693 OPC_Illegal,
2694 OPC_Illegal,
2695 OPC_6502_15,
2696 OPC_6502_16,
2697 OPC_Illegal,
2698 OPC_6502_18,
2699 OPC_6502_19,
2700 OPC_Illegal,
2701 OPC_Illegal,
2702 OPC_Illegal,
2703 OPC_6502_1D,
2704 OPC_6502_1E,
2705 OPC_Illegal,
2706 OPC_6502_20,
2707 OPC_6502_21,
2708 OPC_Illegal,
2709 OPC_Illegal,
2710 OPC_6502_24,
2711 OPC_6502_25,
2712 OPC_6502_26,
2713 OPC_Illegal,
2714 OPC_6502_28,
2715 OPC_6502_29,
2716 OPC_6502_2A,
2717 OPC_Illegal,
2718 OPC_6502_2C,
2719 OPC_6502_2D,
2720 OPC_6502_2E,
2721 OPC_Illegal,
2722 OPC_6502_30,
2723 OPC_6502_31,
2724 OPC_Illegal,
2725 OPC_Illegal,
2726 OPC_Illegal,
2727 OPC_6502_35,
2728 OPC_6502_36,
2729 OPC_Illegal,
2730 OPC_6502_38,
2731 OPC_6502_39,
2732 OPC_Illegal,
2733 OPC_Illegal,
2734 OPC_Illegal,
2735 OPC_6502_3D,
2736 OPC_6502_3E,
2737 OPC_Illegal,
2738 OPC_6502_40,
2739 OPC_6502_41,
2740 OPC_Illegal,
2741 OPC_Illegal,
2742 OPC_Illegal,
2743 OPC_6502_45,
2744 OPC_6502_46,
2745 OPC_Illegal,
2746 OPC_6502_48,
2747 OPC_6502_49,
2748 OPC_6502_4A,
2749 OPC_Illegal,
2750 OPC_6502_4C,
2751 OPC_6502_4D,
2752 OPC_6502_4E,
2753 OPC_Illegal,
2754 OPC_6502_50,
2755 OPC_6502_51,
2756 OPC_Illegal,
2757 OPC_Illegal,
2758 OPC_Illegal,
2759 OPC_6502_55,
2760 OPC_6502_56,
2761 OPC_Illegal,
2762 OPC_6502_58,
2763 OPC_6502_59,
2764 OPC_Illegal,
2765 OPC_Illegal,
2766 OPC_Illegal,
2767 OPC_6502_5D,
2768 OPC_6502_5E,
2769 OPC_Illegal,
2770 OPC_6502_60,
2771 OPC_6502_61,
2772 OPC_Illegal,
2773 OPC_Illegal,
2774 OPC_Illegal,
2775 OPC_6502_65,
2776 OPC_6502_66,
2777 OPC_Illegal,
2778 OPC_6502_68,
2779 OPC_6502_69,
2780 OPC_6502_6A,
2781 OPC_Illegal,
2782 OPC_6502_6C,
2783 OPC_6502_6D,
2784 OPC_6502_6E,
2785 OPC_Illegal,
2786 OPC_6502_70,
2787 OPC_6502_71,
2788 OPC_Illegal,
2789 OPC_Illegal,
2790 OPC_Illegal,
2791 OPC_6502_75,
2792 OPC_6502_76,
2793 OPC_Illegal,
2794 OPC_6502_78,
2795 OPC_6502_79,
2796 OPC_Illegal,
2797 OPC_Illegal,
2798 OPC_Illegal,
2799 OPC_6502_7D,
2800 OPC_6502_7E,
2801 OPC_Illegal,
2802 OPC_Illegal,
2803 OPC_6502_81,
2804 OPC_Illegal,
2805 OPC_Illegal,
2806 OPC_6502_84,
2807 OPC_6502_85,
2808 OPC_6502_86,
2809 OPC_Illegal,
2810 OPC_6502_88,
2811 OPC_Illegal,
2812 OPC_6502_8A,
2813 OPC_Illegal,
2814 OPC_6502_8C,
2815 OPC_6502_8D,
2816 OPC_6502_8E,
2817 OPC_Illegal,
2818 OPC_6502_90,
2819 OPC_6502_91,
2820 OPC_Illegal,
2821 OPC_Illegal,
2822 OPC_6502_94,
2823 OPC_6502_95,
2824 OPC_6502_96,
2825 OPC_Illegal,
2826 OPC_6502_98,
2827 OPC_6502_99,
2828 OPC_6502_9A,
2829 OPC_Illegal,
2830 OPC_Illegal,
2831 OPC_6502_9D,
2832 OPC_Illegal,
2833 OPC_Illegal,
2834 OPC_6502_A0,
2835 OPC_6502_A1,
2836 OPC_6502_A2,
2837 OPC_Illegal,
2838 OPC_6502_A4,
2839 OPC_6502_A5,
2840 OPC_6502_A6,
2841 OPC_Illegal,
2842 OPC_6502_A8,
2843 OPC_6502_A9,
2844 OPC_6502_AA,
2845 OPC_Illegal,
2846 OPC_6502_AC,
2847 OPC_6502_AD,
2848 OPC_6502_AE,
2849 OPC_Illegal,
2850 OPC_6502_B0,
2851 OPC_6502_B1,
2852 OPC_Illegal,
2853 OPC_Illegal,
2854 OPC_6502_B4,
2855 OPC_6502_B5,
2856 OPC_6502_B6,
2857 OPC_Illegal,
2858 OPC_6502_B8,
2859 OPC_6502_B9,
2860 OPC_6502_BA,
2861 OPC_Illegal,
2862 OPC_6502_BC,
2863 OPC_6502_BD,
2864 OPC_6502_BE,
2865 OPC_Illegal,
2866 OPC_6502_C0,
2867 OPC_6502_C1,
2868 OPC_Illegal,
2869 OPC_Illegal,
2870 OPC_6502_C4,
2871 OPC_6502_C5,
2872 OPC_6502_C6,
2873 OPC_Illegal,
2874 OPC_6502_C8,
2875 OPC_6502_C9,
2876 OPC_6502_CA,
2877 OPC_Illegal,
2878 OPC_6502_CC,
2879 OPC_6502_CD,
2880 OPC_6502_CE,
2881 OPC_Illegal,
2882 OPC_6502_D0,
2883 OPC_6502_D1,
2884 OPC_Illegal,
2885 OPC_Illegal,
2886 OPC_Illegal,
2887 OPC_6502_D5,
2888 OPC_6502_D6,
2889 OPC_Illegal,
2890 OPC_6502_D8,
2891 OPC_6502_D9,
2892 OPC_Illegal,
2893 OPC_Illegal,
2894 OPC_Illegal,
2895 OPC_6502_DD,
2896 OPC_6502_DE,
2897 OPC_Illegal,
2898 OPC_6502_E0,
2899 OPC_6502_E1,
2900 OPC_Illegal,
2901 OPC_Illegal,
2902 OPC_6502_E4,
2903 OPC_6502_E5,
2904 OPC_6502_E6,
2905 OPC_Illegal,
2906 OPC_6502_E8,
2907 OPC_6502_E9,
2908 OPC_6502_EA,
2909 OPC_Illegal,
2910 OPC_6502_EC,
2911 OPC_6502_ED,
2912 OPC_6502_EE,
2913 OPC_Illegal,
2914 OPC_6502_F0,
2915 OPC_6502_F1,
2916 OPC_Illegal,
2917 OPC_Illegal,
2918 OPC_Illegal,
2919 OPC_6502_F5,
2920 OPC_6502_F6,
2921 OPC_Illegal,
2922 OPC_6502_F8,
2923 OPC_6502_F9,
2924 OPC_Illegal,
2925 OPC_Illegal,
2926 OPC_Illegal,
2927 OPC_6502_FD,
2928 OPC_6502_FE,
2929 OPC_Illegal,
2930};
2931
2932
2933
2934/* Opcode handler table for the 65C02 */
2935static const OPFunc OP65C02Table[256] = {
2936 OPC_6502_00,
2937 OPC_6502_01,
2938 OPC_65C02_NOP22, // $02
2939 OPC_65C02_NOP11, // $03
2940 OPC_65SC02_04,
2941 OPC_6502_05,
2942 OPC_6502_06,
2943 OPC_Illegal, // $07: RMB0 currently unsupported
2944 OPC_6502_08,
2945 OPC_6502_09,
2946 OPC_6502_0A,
2947 OPC_65C02_NOP11, // $0B
2948 OPC_65SC02_0C,
2949 OPC_6502_0D,
2950 OPC_6502_0E,
2951 OPC_Illegal, // $0F: BBR0 currently unsupported
2952 OPC_6502_10,
2953 OPC_6502_11,
2954 OPC_65SC02_12,
2955 OPC_65C02_NOP11, // $13
2956 OPC_65SC02_14,
2957 OPC_6502_15,
2958 OPC_6502_16,
2959 OPC_Illegal, // $17: RMB1 currently unsupported
2960 OPC_6502_18,
2961 OPC_6502_19,
2962 OPC_65SC02_1A,
2963 OPC_65C02_NOP11, // $1B
2964 OPC_65SC02_1C,
2965 OPC_6502_1D,
2966 OPC_6502_1E,
2967 OPC_Illegal, // $1F: BBR1 currently unsupported
2968 OPC_6502_20,
2969 OPC_6502_21,
2970 OPC_65C02_NOP22, // $22
2971 OPC_65C02_NOP11, // $23
2972 OPC_6502_24,
2973 OPC_6502_25,
2974 OPC_6502_26,
2975 OPC_Illegal, // $27: RMB2 currently unsupported
2976 OPC_6502_28,
2977 OPC_6502_29,
2978 OPC_6502_2A,
2979 OPC_65C02_NOP11, // $2B
2980 OPC_6502_2C,
2981 OPC_6502_2D,
2982 OPC_6502_2E,
2983 OPC_Illegal, // $2F: BBR2 currently unsupported
2984 OPC_6502_30,
2985 OPC_6502_31,
2986 OPC_65SC02_32,
2987 OPC_65C02_NOP11, // $33
2988 OPC_65SC02_34,
2989 OPC_6502_35,
2990 OPC_6502_36,
2991 OPC_Illegal, // $37: RMB3 currently unsupported
2992 OPC_6502_38,
2993 OPC_6502_39,
2994 OPC_65SC02_3A,
2995 OPC_65C02_NOP11, // $3B
2996 OPC_65SC02_3C,
2997 OPC_6502_3D,
2998 OPC_6502_3E,
2999 OPC_Illegal, // $3F: BBR3 currently unsupported
3000 OPC_6502_40,
3001 OPC_6502_41,
3002 OPC_65C02_NOP22, // $42
3003 OPC_65C02_NOP11, // $43
3004 OPC_65C02_44, // $44
3005 OPC_6502_45,
3006 OPC_6502_46,
3007 OPC_Illegal, // $47: RMB4 currently unsupported
3008 OPC_6502_48,
3009 OPC_6502_49,
3010 OPC_6502_4A,
3011 OPC_65C02_NOP11, // $4B
3012 OPC_6502_4C,
3013 OPC_6502_4D,
3014 OPC_6502_4E,
3015 OPC_Illegal, // $4F: BBR4 currently unsupported
3016 OPC_6502_50,
3017 OPC_6502_51,
3018 OPC_65SC02_52,
3019 OPC_65C02_NOP11, // $53
3020 OPC_65C02_NOP24, // $54
3021 OPC_6502_55,
3022 OPC_6502_56,
3023 OPC_Illegal, // $57: RMB5 currently unsupported
3024 OPC_6502_58,
3025 OPC_6502_59,
3026 OPC_65SC02_5A,
3027 OPC_65C02_NOP11, // $5B
3028 OPC_65C02_5C,
3029 OPC_6502_5D,
3030 OPC_6502_5E,
3031 OPC_Illegal, // $5F: BBR5 currently unsupported
3032 OPC_6502_60,
3033 OPC_6502_61,
3034 OPC_65C02_NOP22, // $62
3035 OPC_65C02_NOP11, // $63
3036 OPC_65SC02_64,
3037 OPC_6502_65,
3038 OPC_6502_66,
3039 OPC_Illegal, // $67: RMB6 currently unsupported
3040 OPC_6502_68,
3041 OPC_6502_69,
3042 OPC_6502_6A,
3043 OPC_65C02_NOP11, // $6B
3044 OPC_65C02_6C,
3045 OPC_6502_6D,
3046 OPC_6502_6E,
3047 OPC_Illegal, // $6F: BBR6 currently unsupported
3048 OPC_6502_70,
3049 OPC_6502_71,
3050 OPC_65SC02_72,
3051 OPC_65C02_NOP11, // $73
3052 OPC_65SC02_74,
3053 OPC_6502_75,
3054 OPC_6502_76,
3055 OPC_Illegal, // $77: RMB7 currently unsupported
3056 OPC_6502_78,
3057 OPC_6502_79,
3058 OPC_65SC02_7A,
3059 OPC_65C02_NOP11, // $7B
3060 OPC_65SC02_7C,
3061 OPC_6502_7D,
3062 OPC_6502_7E,
3063 OPC_Illegal, // $7F: BBR7 currently unsupported
3064 OPC_65SC02_80,
3065 OPC_6502_81,
3066 OPC_65C02_NOP22, // $82
3067 OPC_65C02_NOP11, // $83
3068 OPC_6502_84,
3069 OPC_6502_85,
3070 OPC_6502_86,
3071 OPC_Illegal, // $87: SMB0 currently unsupported
3072 OPC_6502_88,
3073 OPC_65SC02_89,
3074 OPC_6502_8A,
3075 OPC_65C02_NOP11, // $8B
3076 OPC_6502_8C,
3077 OPC_6502_8D,
3078 OPC_6502_8E,
3079 OPC_Illegal, // $8F: BBS0 currently unsupported
3080 OPC_6502_90,
3081 OPC_6502_91,
3082 OPC_65SC02_92,
3083 OPC_65C02_NOP11, // $93
3084 OPC_6502_94,
3085 OPC_6502_95,
3086 OPC_6502_96,
3087 OPC_Illegal, // $97: SMB1 currently unsupported
3088 OPC_6502_98,
3089 OPC_6502_99,
3090 OPC_6502_9A,
3091 OPC_65C02_NOP11, // $9B
3092 OPC_65SC02_9C,
3093 OPC_6502_9D,
3094 OPC_65SC02_9E,
3095 OPC_Illegal, // $9F: BBS1 currently unsupported
3096 OPC_6502_A0,
3097 OPC_6502_A1,
3098 OPC_6502_A2,
3099 OPC_65C02_NOP11, // $A3
3100 OPC_6502_A4,
3101 OPC_6502_A5,
3102 OPC_6502_A6,
3103 OPC_Illegal, // $A7: SMB2 currently unsupported
3104 OPC_6502_A8,
3105 OPC_6502_A9,
3106 OPC_6502_AA,
3107 OPC_65C02_NOP11, // $AB
3108 OPC_6502_AC,
3109 OPC_6502_AD,
3110 OPC_6502_AE,
3111 OPC_Illegal, // $AF: BBS2 currently unsupported
3112 OPC_6502_B0,
3113 OPC_6502_B1,
3114 OPC_65SC02_B2,
3115 OPC_65C02_NOP11, // $B3
3116 OPC_6502_B4,
3117 OPC_6502_B5,
3118 OPC_6502_B6,
3119 OPC_Illegal, // $B7: SMB3 currently unsupported
3120 OPC_6502_B8,
3121 OPC_6502_B9,
3122 OPC_6502_BA,
3123 OPC_65C02_NOP11, // $BB
3124 OPC_6502_BC,
3125 OPC_6502_BD,
3126 OPC_6502_BE,
3127 OPC_Illegal, // $BF: BBS3 currently unsupported
3128 OPC_6502_C0,
3129 OPC_6502_C1,
3130 OPC_65C02_NOP22, // $C2
3131 OPC_65C02_NOP11, // $C3
3132 OPC_6502_C4,
3133 OPC_6502_C5,
3134 OPC_6502_C6,
3135 OPC_Illegal, // $C7: SMB4 currently unsupported
3136 OPC_6502_C8,
3137 OPC_6502_C9,
3138 OPC_6502_CA,
3139 OPC_Illegal, // $CB: WAI currently unsupported
3140 OPC_6502_CC,
3141 OPC_6502_CD,
3142 OPC_6502_CE,
3143 OPC_Illegal, // $CF: BBS4 currently unsupported
3144 OPC_6502_D0,
3145 OPC_6502_D1,
3146 OPC_65SC02_D2,
3147 OPC_65C02_NOP11, // $D3
3148 OPC_65C02_NOP24, // $D4
3149 OPC_6502_D5,
3150 OPC_6502_D6,
3151 OPC_Illegal, // $D7: SMB5 currently unsupported
3152 OPC_6502_D8,
3153 OPC_6502_D9,
3154 OPC_65SC02_DA,
3155 OPC_Illegal, // $DB: STP currently unsupported
3156 OPC_65C02_NOP34, // $DC
3157 OPC_6502_DD,
3158 OPC_6502_DE,
3159 OPC_Illegal, // $DF: BBS5 currently unsupported
3160 OPC_6502_E0,
3161 OPC_6502_E1,
3162 OPC_65C02_NOP22, // $E2
3163 OPC_65C02_NOP11, // $E3
3164 OPC_6502_E4,
3165 OPC_6502_E5,
3166 OPC_6502_E6,
3167 OPC_Illegal, // $E7: SMB6 currently unsupported
3168 OPC_6502_E8,
3169 OPC_6502_E9,
3170 OPC_6502_EA,
3171 OPC_65C02_NOP11, // $EB
3172 OPC_6502_EC,
3173 OPC_6502_ED,
3174 OPC_6502_EE,
3175 OPC_Illegal, // $EF: BBS6 currently unsupported
3176 OPC_6502_F0,
3177 OPC_6502_F1,
3178 OPC_65SC02_F2,
3179 OPC_65C02_NOP11, // $F3
3180 OPC_65C02_NOP24, // $F4
3181 OPC_6502_F5,
3182 OPC_6502_F6,
3183 OPC_Illegal, // $F7: SMB7 currently unsupported
3184 OPC_6502_F8,
3185 OPC_6502_F9,
3186 OPC_65SC02_FA,
3187 OPC_65C02_NOP11, // $FB
3188 OPC_65C02_NOP34, // $FC
3189 OPC_6502_FD,
3190 OPC_6502_FE,
3191 OPC_Illegal, // $FF: BBS7 currently unsupported
3192};
3193
3194
3195
3196/* Tables with opcode handlers */
3197static const OPFunc* Handlers[2] = {OP6502Table, OP65C02Table};
3198
3199
3200
3201/*****************************************************************************/
3202/* Code */
3203/*****************************************************************************/
3204
3205
3206
3207void IRQRequest (void)
3208/* Generate an IRQ */
3209{
3210 /* Remember the request */
3211 HaveIRQRequest = 1;
3212}
3213
3214
3215
3216void NMIRequest (void)
3217/* Generate an NMI */
3218{
3219 /* Remember the request */
3220 HaveNMIRequest = 1;
3221}
3222
3223
3224
3225void Reset (void)
3226/* Generate a CPU RESET */
3227{
3228 /* Reset the CPU */
3229 HaveIRQRequest = 0;
3230 HaveNMIRequest = 0;
3231
3232 /* Bits 5 and 4 aren't used, and always are 1! */
3233 Regs.SR = 0x30;
3234 Regs.PC = MemReadWord (0xFFFC);
3235}
3236
3237
3238
3239unsigned ExecuteInsn (void)
3240/* Execute one CPU instruction */
3241{
3242 /* If we have an NMI request, handle it */
3243 if (HaveNMIRequest) {
3244
3245 HaveNMIRequest = 0;
3246 PUSH (PCH);
3247 PUSH (PCL);
3248 PUSH (Regs.SR & ~BF);
3249 SET_IF (1);
3250 if (CPU != CPU_6502)
3251 {
3252 SET_DF (0);
3253 }
3254 Regs.PC = MemReadWord (0xFFFA);
3255 Cycles = 7;
3256
3257 } else if (HaveIRQRequest && GET_IF () == 0) {
3258
3259 HaveIRQRequest = 0;
3260 PUSH (PCH);
3261 PUSH (PCL);
3262 PUSH (Regs.SR & ~BF);
3263 SET_IF (1);
3264 if (CPU != CPU_6502)
3265 {
3266 SET_DF (0);
3267 }
3268 Regs.PC = MemReadWord (0xFFFE);
3269 Cycles = 7;
3270
3271 } else {
3272
3273 /* Normal instruction - read the next opcode */
3274 unsigned char OPC = MemReadByte (Regs.PC);
3275
3276 /* Execute it */
3277 Handlers[CPU][OPC] ();
3278 }
3279
3280 /* Count cycles */
3281 TotalCycles += Cycles;
3282
3283 /* Return the number of clock cycles needed by this insn */
3284 return Cycles;
3285}
3286
3287
3288
3289unsigned long GetCycles (void)
3290/* Return the total number of cycles executed */
3291{
3292 /* Return the total number of cycles */
3293 return TotalCycles;
3294}
3295