]> git.sur5r.net Git - cc65/blob - src/sim65/cpucore.c
8f7e35f8032305faf26f76c3d5b7ab2cc496b5e7
[cc65] / src / sim65 / cpucore.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                   cpucore.c                               */
4 /*                                                                           */
5 /*                        CPU core for the 6502 simulator                    */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2002-2003 Ullrich von Bassewitz                                       */
10 /*               Römerstrasse 52                                             */
11 /*               D-70794 Filderstadt                                         */
12 /* EMail:        uz@cc65.org                                                 */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <stdlib.h>
37
38 /* common */
39 #include "abend.h"
40 #include "attrib.h"
41 #include "print.h"
42
43 /* sim65 */
44 #include "cputype.h"
45 #include "error.h"
46 #include "global.h"
47 #include "memory.h"
48 #include "cpucore.h"
49
50
51
52 /*****************************************************************************/
53 /*                                   Data                                    */
54 /*****************************************************************************/
55
56
57
58 /* Registers */
59 unsigned char   AC;             /* Accumulator */
60 unsigned char   XR;             /* X register */
61 unsigned char   YR;             /* Y register */
62 unsigned char   SR;             /* Status register */
63 unsigned char   SP;             /* Stackpointer */
64 unsigned        PC;             /* Program counter */
65
66 /* Count the total number of cylcles */
67 unsigned        Cycles;         /* Cycles per insn */
68 unsigned long   TotalCycles;    /* Total cycles */
69
70 /* Allow the stack page to be changed */
71 static unsigned StackPage = 0x100;
72
73 /* Status register bits */
74 #define CF      0x01            /* Carry flag */
75 #define ZF      0x02            /* Zero flag */
76 #define IF      0x04            /* Interrupt flag */
77 #define DF      0x08            /* Decimal flag */
78 #define BF      0x10            /* Break flag */
79 #define OF      0x40            /* Overflow flag */
80 #define SF      0x80            /* Sign flag */
81
82 /* */
83 int CPUHalted;
84
85
86
87 /*****************************************************************************/
88 /*                        Helper functions and macros                        */
89 /*****************************************************************************/
90
91
92
93 /* Return the flags as a boolean value (0/1) */
94 #define GET_CF()        ((SR & CF) != 0)
95 #define GET_ZF()        ((SR & ZF) != 0)
96 #define GET_IF()        ((SR & IF) != 0)
97 #define GET_DF()        ((SR & DF) != 0)
98 #define GET_BF()        ((SR & BF) != 0)
99 #define GET_OF()        ((SR & OF) != 0)
100 #define GET_SF()        ((SR & SF) != 0)
101
102 /* Set the flags. The parameter is a boolean flag that says if the flag should be
103  * set or reset.
104  */
105 #define SET_CF(f)       do { if (f) { SR |= CF; } else { SR &= ~CF; } } while (0)
106 #define SET_ZF(f)       do { if (f) { SR |= ZF; } else { SR &= ~ZF; } } while (0)
107 #define SET_IF(f)       do { if (f) { SR |= IF; } else { SR &= ~IF; } } while (0)
108 #define SET_DF(f)       do { if (f) { SR |= DF; } else { SR &= ~DF; } } while (0)
109 #define SET_BF(f)       do { if (f) { SR |= BF; } else { SR &= ~BF; } } while (0)
110 #define SET_OF(f)       do { if (f) { SR |= OF; } else { SR &= ~OF; } } while (0)
111 #define SET_SF(f)       do { if (f) { SR |= SF; } else { SR &= ~SF; } } while (0)
112
113 /* Special test and set macros. The meaning of the parameter depends on the
114  * actual flag that should be set or reset.
115  */
116 #define TEST_ZF(v)      SET_ZF (((v) & 0xFF) == 0)
117 #define TEST_SF(v)      SET_SF (((v) & 0x80) != 0)
118 #define TEST_CF(v)      SET_CF (((v) & 0xFF00) != 0)
119
120 /* Program counter halves */
121 #define PCL             (PC & 0xFF)
122 #define PCH             ((PC >> 8) & 0xFF)
123
124 /* Stack operations */
125 #define PUSH(Val)       MemWriteByte (StackPage + SP--, Val)
126 #define POP()           MemReadByte (StackPage + ++SP)
127
128 /* Test for page cross */
129 #define PAGE_CROSS(addr,offs)   ((((addr) & 0xFF) + offs) >= 0x100)
130
131 /* #imm */
132 #define AC_OP_IMM(op)                           \
133     Cycles = 2;                                 \
134     AC = AC op MemReadByte (PC+1);              \
135     TEST_ZF (AC);                               \
136     TEST_SF (AC);                               \
137     PC += 2
138
139 /* zp */
140 #define AC_OP_ZP(op)                            \
141     Cycles = 3;                                 \
142     AC = AC op MemReadByte (MemReadByte (PC+1));\
143     TEST_ZF (AC);                               \
144     TEST_SF (AC);                               \
145     PC += 2
146
147 /* zp,x */
148 #define AC_OP_ZPX(op)                           \
149     unsigned char ZPAddr;                       \
150     Cycles = 4;                                 \
151     ZPAddr = MemReadByte (PC+1) + XR;           \
152     AC = AC op MemReadByte (ZPAddr);            \
153     TEST_ZF (AC);                               \
154     TEST_SF (AC);                               \
155     PC += 2
156
157 /* zp,y */
158 #define AC_OP_ZPY(op)                           \
159     unsigned char ZPAddr;                       \
160     Cycles = 4;                                 \
161     ZPAddr = MemReadByte (PC+1) + YR;           \
162     AC = AC op MemReadByte (ZPAddr);            \
163     TEST_ZF (AC);                               \
164     TEST_SF (AC);                               \
165     PC += 2
166
167 /* abs */
168 #define AC_OP_ABS(op)                           \
169     unsigned Addr;                              \
170     Cycles = 4;                                 \
171     Addr = MemReadWord (PC+1);                  \
172     AC = AC op MemReadByte (Addr);              \
173     TEST_ZF (AC);                               \
174     TEST_SF (AC);                               \
175     PC += 3
176
177 /* abs,x */
178 #define AC_OP_ABSX(op)                          \
179     unsigned Addr;                              \
180     Cycles = 4;                                 \
181     Addr = MemReadWord (PC+1);                  \
182     if (PAGE_CROSS (Addr, XR)) {                \
183         ++Cycles;                               \
184     }                                           \
185     AC = AC | MemReadByte (Addr + XR);          \
186     TEST_ZF (AC);                               \
187     TEST_SF (AC);                               \
188     PC += 3
189
190 /* abs,y */
191 #define AC_OP_ABSY(op)                          \
192     unsigned Addr;                              \
193     Cycles = 4;                                 \
194     Addr = MemReadWord (PC+1);                  \
195     if (PAGE_CROSS (Addr, YR)) {                \
196         ++Cycles;                               \
197     }                                           \
198     AC = AC | MemReadByte (Addr + YR);          \
199     TEST_ZF (AC);                               \
200     TEST_SF (AC);                               \
201     PC += 3
202
203 /* (zp,x) */
204 #define AC_OP_ZPXIND(op)                        \
205     unsigned char ZPAddr;                       \
206     unsigned Addr;                              \
207     Cycles = 6;                                 \
208     ZPAddr = MemReadByte (PC+1) + XR;           \
209     Addr = MemReadZPWord (ZPAddr);              \
210     AC = AC op MemReadByte (Addr);              \
211     TEST_ZF (AC);                               \
212     TEST_SF (AC);                               \
213     PC += 2
214
215 /* (zp),y */
216 #define AC_OP_ZPINDY(op)                        \
217     unsigned char ZPAddr;                       \
218     unsigned Addr;                              \
219     Cycles = 5;                                 \
220     ZPAddr = MemReadByte (PC+1);                \
221     Addr = MemReadZPWord (ZPAddr) + YR;         \
222     AC = AC op MemReadByte (Addr);              \
223     TEST_ZF (AC);                               \
224     TEST_SF (AC);                               \
225     PC += 2
226
227 /* ADC */
228 #define ADC(v)                                  \
229     if (GET_DF ()) {                            \
230         Warning ("Decimal mode not available"); \
231     } else {                                    \
232         unsigned Val;                           \
233         unsigned char rhs = v;                  \
234         Val = AC + rhs + GET_CF ();             \
235         AC = (unsigned char) Val;               \
236         TEST_ZF (AC);                           \
237         TEST_SF (AC);                           \
238         TEST_CF (Val);                          \
239         SET_OF (!((AC ^ rhs) & 0x80) &&         \
240                 ((AC ^ Val) & 0x80));           \
241     }
242
243 /* branches */
244 #define BRANCH(cond)                            \
245     Cycles = 2;                                 \
246     if (cond) {                                 \
247         signed char Offs;                       \
248         unsigned char OldPCH;                   \
249         ++Cycles;                               \
250         Offs = (signed char) MemReadByte (PC+1);\
251         OldPCH = PCH;                           \
252         PC += 2 + (int) Offs;                   \
253         if (PCH != OldPCH) {                    \
254             ++Cycles;                           \
255         }                                       \
256     } else {                                    \
257         PC += 2;                                \
258     }
259
260 /* compares */
261 #define CMP(v1,v2)                              \
262     {                                           \
263         unsigned Result = v1 - v2;              \
264         TEST_ZF (Result & 0xFF);                \
265         TEST_SF (Result);                       \
266         SET_CF (Result <= 0xFF);                \
267     }
268
269
270 /* ROL */
271 #define ROL(Val)                                \
272     Val <<= 1;                                  \
273     if (GET_CF ()) {                            \
274         Val |= 0x01;                            \
275     }                                           \
276     TEST_ZF (Val);                              \
277     TEST_SF (Val);                              \
278     TEST_CF (Val)
279
280 /* ROR */
281 #define ROR(Val)                                \
282     if (GET_CF ()) {                            \
283         Val |= 0x100;                           \
284     }                                           \
285     SET_CF (Val & 0x01);                        \
286     Val >>= 1;                                  \
287     TEST_ZF (Val);                              \
288     TEST_SF (Val)
289
290 /* SBC */
291 #define SBC(v)                                  \
292     if (GET_DF ()) {                            \
293         Warning ("Decimal mode not available"); \
294     } else {                                    \
295         unsigned Val;                           \
296         unsigned char rhs = v;                  \
297         Val = AC - rhs - (!GET_CF ());          \
298         AC = (unsigned char) Val;               \
299         TEST_ZF (AC);                           \
300         TEST_SF (AC);                           \
301         SET_CF (Val <= 0xFF);                   \
302         SET_OF (((AC^rhs) & (AC^Val) & 0x80));  \
303     }
304
305
306
307 /*****************************************************************************/
308 /*                               Helper functions                            */
309 /*****************************************************************************/
310
311
312
313 static void OPC_Illegal (void)
314 {
315     Warning ("Illegal opcode $%02X at address $%04X\n", MemReadByte (PC), PC);
316 }
317
318
319
320 /*****************************************************************************/
321 /*                                   Code                                    */
322 /*****************************************************************************/
323
324
325
326 static void OPC_6502_00 (void)
327 /* Opcode $00: BRK */
328 {
329     Cycles = 7;
330     PC += 2;
331     SET_BF (1);
332     PUSH (PCH);
333     PUSH (PCL);
334     PUSH (SR);
335     SET_IF (1);
336     PC = MemReadWord (0xFFFE);
337     CPUHalted = 1;
338 }
339
340
341
342 static void OPC_6502_01 (void)
343 /* Opcode $01: ORA (ind,x) */
344 {
345     AC_OP_ZPXIND (|);
346 }
347
348
349
350 static void OPC_6502_05 (void)
351 /* Opcode $05: ORA zp */
352 {
353     AC_OP_ZP (|);
354 }
355
356
357
358 static void OPC_6502_06 (void)
359 /* Opcode $06: ASL zp */
360 {
361     unsigned char ZPAddr;
362     unsigned Val;
363     Cycles = 5;
364     ZPAddr = MemReadByte (PC+1);
365     Val    = MemReadByte (ZPAddr) << 1;
366     MemWriteByte (ZPAddr, (unsigned char) Val);
367     TEST_ZF (Val & 0xFF);
368     TEST_SF (Val);
369     SET_CF (Val & 0x100);
370     PC += 2;
371 }
372
373
374
375 static void OPC_6502_08 (void)
376 /* Opcode $08: PHP */
377 {
378     Cycles = 3;
379     PUSH (SR & ~BF);
380     PC += 1;
381 }
382
383
384
385 static void OPC_6502_09 (void)
386 /* Opcode $09: ORA #imm */
387 {
388     AC_OP_IMM (|);
389 }
390
391
392
393 static void OPC_6502_0A (void)
394 /* Opcode $0A: ASL a */
395 {
396     unsigned Val;
397     Cycles = 2;
398     Val    = AC << 1;
399     AC     = (unsigned char) Val;
400     TEST_ZF (Val & 0xFF);
401     TEST_SF (Val);
402     SET_CF (Val & 0x100);
403     PC += 1;
404 }
405
406
407
408 static void OPC_6502_0D (void)
409 /* Opcode $0D: ORA abs */
410 {
411     AC_OP_ABS (|);
412 }
413
414
415
416 static void OPC_6502_0E (void)
417 /* Opcode $0E: ALS abs */
418 {
419     unsigned Addr;
420     unsigned Val;
421     Cycles = 6;
422     Addr = MemReadWord (PC+1);
423     Val  = MemReadByte (Addr) << 1;
424     MemWriteByte (Addr, (unsigned char) Val);
425     TEST_ZF (Val & 0xFF);
426     TEST_SF (Val);
427     SET_CF (Val & 0x100);
428     PC += 3;
429 }
430
431
432
433 static void OPC_6502_10 (void)
434 /* Opcode $10: BPL */
435 {
436     BRANCH (!GET_SF ());
437 }
438
439
440
441 static void OPC_6502_11 (void)
442 /* Opcode $11: ORA (zp),y */
443 {
444     AC_OP_ZPINDY (|);
445 }
446
447
448
449 static void OPC_6502_15 (void)
450 /* Opcode $15: ORA zp,x */
451 {
452    AC_OP_ZPX (|);
453 }
454
455
456
457 static void OPC_6502_16 (void)
458 /* Opcode $16: ASL zp,x */
459 {
460     unsigned char ZPAddr;
461     unsigned Val;
462     Cycles = 6;
463     ZPAddr = MemReadByte (PC+1) + XR;
464     Val    = MemReadByte (ZPAddr) << 1;
465     MemWriteByte (ZPAddr, (unsigned char) Val);
466     TEST_ZF (Val & 0xFF);
467     TEST_SF (Val);
468     SET_CF (Val & 0x100);
469     PC += 2;
470 }
471
472
473
474 static void OPC_6502_18 (void)
475 /* Opcode $18: CLC */
476 {
477     Cycles = 2;
478     SET_CF (0);
479     PC += 1;
480 }
481
482
483
484 static void OPC_6502_19 (void)
485 /* Opcode $19: ORA abs,y */
486 {
487     AC_OP_ABSY (|);
488 }
489
490
491
492 static void OPC_6502_1D (void)
493 /* Opcode $1D: ORA abs,x */
494 {
495     AC_OP_ABSX (|);
496 }
497
498
499
500 static void OPC_6502_1E (void)
501 /* Opcode $1E: ASL abs,x */
502 {
503     unsigned Addr;
504     unsigned Val;
505     Cycles = 7;
506     Addr = MemReadWord (PC+1) + XR;
507     Val  = MemReadByte (Addr) << 1;
508     MemWriteByte (Addr, (unsigned char) Val);
509     TEST_ZF (Val & 0xFF);
510     TEST_SF (Val);
511     SET_CF (Val & 0x100);
512     PC += 3;
513 }
514
515
516
517 static void OPC_6502_20 (void)
518 /* Opcode $20: JSR */
519 {
520     unsigned Addr;
521     Cycles = 6;
522     Addr   = MemReadWord (PC+1);
523     PC += 2;
524     PUSH (PCH);
525     PUSH (PCL);
526     PC = Addr;
527 }
528
529
530
531 static void OPC_6502_21 (void)
532 /* Opcode $21: AND (zp,x) */
533 {
534     AC_OP_ZPXIND (&);
535 }
536
537
538
539 static void OPC_6502_24 (void)
540 /* Opcode $24: BIT zp */
541 {
542     unsigned char ZPAddr;
543     unsigned char Val;
544     Cycles = 3;
545     ZPAddr = MemReadByte (PC+1);
546     Val    = MemReadByte (ZPAddr);
547     SET_SF (Val & 0x80);
548     SET_OF (Val & 0x40);
549     SET_ZF ((Val & AC) == 0);
550     PC += 2;
551 }
552
553
554
555 static void OPC_6502_25 (void)
556 /* Opcode $25: AND zp */
557 {
558     AC_OP_ZP (&);
559 }
560
561
562
563 static void OPC_6502_26 (void)
564 /* Opcode $26: ROL zp */
565 {
566     unsigned char ZPAddr;
567     unsigned Val;
568     Cycles = 5;
569     ZPAddr = MemReadByte (PC+1);
570     Val    = MemReadByte (ZPAddr);
571     ROL (Val);
572     MemWriteByte (ZPAddr, Val);
573     PC += 2;
574 }
575
576
577
578 static void OPC_6502_28 (void)
579 /* Opcode $28: PLP */
580 {
581     Cycles = 4;
582     SR = (POP () & ~BF);
583     PC += 1;
584 }
585
586
587
588 static void OPC_6502_29 (void)
589 /* Opcode $29: AND #imm */
590 {
591     AC_OP_IMM (&);
592 }
593
594
595
596 static void OPC_6502_2A (void)
597 /* Opcode $2A: ROL a */
598 {
599     unsigned Val;
600     Cycles = 2;
601     Val    = AC;
602     ROL (Val);
603     AC = (unsigned char) Val;
604     PC += 1;
605 }
606
607
608
609 static void OPC_6502_2C (void)
610 /* Opcode $2C: BIT abs */
611 {
612     unsigned Addr;
613     unsigned char Val;
614     Cycles = 4;
615     Addr = MemReadByte (PC+1);
616     Val  = MemReadByte (Addr);
617     SET_SF (Val & 0x80);
618     SET_OF (Val & 0x40);
619     SET_ZF ((Val & AC) == 0);
620     PC += 3;
621 }
622
623
624
625 static void OPC_6502_2D (void)
626 /* Opcode $2D: AND abs */
627 {
628     AC_OP_ABS (&);
629 }
630
631
632
633 static void OPC_6502_2E (void)
634 /* Opcode $2E: ROL abs */
635 {
636     unsigned Addr;
637     unsigned Val;
638     Cycles = 6;
639     Addr = MemReadWord (PC+1);
640     Val  = MemReadByte (Addr);
641     ROL (Val);
642     MemWriteByte (Addr, Val);
643     PC += 3;
644 }
645
646
647
648 static void OPC_6502_30 (void)
649 /* Opcode $30: BMI */
650 {
651     BRANCH (GET_SF ());
652 }
653
654
655
656 static void OPC_6502_31 (void)
657 /* Opcode $31: AND (zp),y */
658 {
659     AC_OP_ZPINDY (&);
660 }
661
662
663
664 static void OPC_6502_35 (void)
665 /* Opcode $35: AND zp,x */
666 {
667     AC_OP_ZPX (&);
668 }
669
670
671
672 static void OPC_6502_36 (void)
673 /* Opcode $36: ROL zp,x */
674 {
675     unsigned char ZPAddr;
676     unsigned Val;
677     Cycles = 6;
678     ZPAddr = MemReadByte (PC+1) + XR;
679     Val    = MemReadByte (ZPAddr);
680     ROL (Val);
681     MemWriteByte (ZPAddr, Val);
682     PC += 2;
683 }
684
685
686
687 static void OPC_6502_38 (void)
688 /* Opcode $38: SEC */
689 {
690     Cycles = 2;
691     SET_CF (1);
692     PC += 1;
693 }
694
695
696
697 static void OPC_6502_39 (void)
698 /* Opcode $39: AND abs,y */
699 {
700     AC_OP_ABSY (&);
701 }
702
703
704
705 static void OPC_6502_3D (void)
706 /* Opcode $3D: AND abs,x */
707 {
708     AC_OP_ABSX (&);
709 }
710
711
712
713 static void OPC_6502_3E (void)
714 /* Opcode $3E: ROL abs,x */
715 {
716     unsigned Addr;
717     unsigned Val;
718     Cycles = 7;
719     Addr = MemReadWord (PC+1) + XR;
720     Val  = MemReadByte (Addr);
721     ROL (Val);
722     MemWriteByte (Addr, Val);
723     PC += 2;
724 }
725
726
727
728 static void OPC_6502_40 (void)
729 /* Opcode $40: RTI */
730 {
731     Cycles = 6;
732     SR = POP ();
733     PC = POP ();                /* PCL */
734     PC |= (POP () << 8);        /* PCH */
735 }
736
737
738
739 static void OPC_6502_41 (void)
740 /* Opcode $41: EOR (zp,x) */
741 {
742     AC_OP_ZPXIND (^);
743 }
744
745
746
747 static void OPC_6502_45 (void)
748 /* Opcode $45: EOR zp */
749 {
750     AC_OP_ZP (^);
751 }
752
753
754
755 static void OPC_6502_46 (void)
756 /* Opcode $46: LSR zp */
757 {
758     unsigned char ZPAddr;
759     unsigned char Val;
760     Cycles = 5;
761     ZPAddr = MemReadByte (PC+1);
762     Val    = MemReadByte (ZPAddr);
763     SET_CF (Val & 0x01);
764     Val >>= 1;
765     MemWriteByte (ZPAddr, Val);
766     TEST_ZF (Val);
767     TEST_SF (Val);
768     PC += 2;
769 }
770
771
772
773 static void OPC_6502_48 (void)
774 /* Opcode $48: PHA */
775 {
776     Cycles = 3;
777     PUSH (AC);
778     PC += 1;
779 }
780
781
782
783 static void OPC_6502_49 (void)
784 /* Opcode $49: EOR #imm */
785 {
786     AC_OP_IMM (^);
787 }
788
789
790
791 static void OPC_6502_4A (void)
792 /* Opcode $4A: LSR a */
793 {
794     Cycles = 2;
795     SET_CF (AC & 0x01);
796     AC >>= 1;
797     TEST_ZF (AC);
798     TEST_SF (AC);
799     PC += 1;
800 }
801
802
803
804 static void OPC_6502_4C (void)
805 /* Opcode $4C: JMP abs */
806 {
807     Cycles = 3;
808     PC = MemReadWord (PC+1);
809 }
810
811
812
813 static void OPC_6502_4D (void)
814 /* Opcode $4D: EOR abs */
815 {
816     AC_OP_ABS (^);
817 }
818
819
820
821 static void OPC_6502_4E (void)
822 /* Opcode $4E: LSR abs */
823 {
824     unsigned Addr;
825     unsigned char Val;
826     Cycles = 6;
827     Addr = MemReadWord (PC+1);
828     Val  = MemReadByte (Addr);
829     SET_CF (Val & 0x01);
830     Val >>= 1;
831     MemWriteByte (Addr, Val);
832     TEST_ZF (Val);
833     TEST_SF (Val);
834     PC += 3;
835 }
836
837
838
839 static void OPC_6502_50 (void)
840 /* Opcode $50: BVC */
841 {
842     BRANCH (!GET_OF ());
843 }
844
845
846
847 static void OPC_6502_51 (void)
848 /* Opcode $51: EOR (zp),y */
849 {
850     AC_OP_ZPINDY (^);
851 }
852
853
854
855 static void OPC_6502_55 (void)
856 /* Opcode $55: EOR zp,x */
857 {
858     AC_OP_ZPX (^);
859 }
860
861
862
863 static void OPC_6502_56 (void)
864 /* Opcode $56: LSR zp,x */
865 {
866     unsigned char ZPAddr;
867     unsigned char Val;
868     Cycles = 6;
869     ZPAddr = MemReadByte (PC+1) + XR;
870     Val    = MemReadByte (ZPAddr);
871     SET_CF (Val & 0x01);
872     Val >>= 1;
873     MemWriteByte (ZPAddr, Val);
874     TEST_ZF (Val);
875     TEST_SF (Val);
876     PC += 2;
877 }
878
879
880
881 static void OPC_6502_58 (void)
882 /* Opcode $58: CLI */
883 {
884     Cycles = 2;
885     SET_IF (0);
886     PC += 1;
887 }
888
889
890
891 static void OPC_6502_59 (void)
892 /* Opcode $59: EOR abs,y */
893 {
894     AC_OP_ABSY (^);
895 }
896
897
898
899 static void OPC_6502_5D (void)
900 /* Opcode $5D: EOR abs,x */
901 {
902     AC_OP_ABSX (^);
903 }
904
905
906
907 static void OPC_6502_5E (void)
908 /* Opcode $5E: LSR abs,x */
909 {
910     unsigned Addr;
911     unsigned char Val;
912     Cycles = 7;
913     Addr = MemReadWord (PC+1) + XR;
914     Val  = MemReadByte (Addr);
915     SET_CF (Val & 0x01);
916     Val >>= 1;
917     MemWriteByte (Addr, Val);
918     TEST_ZF (Val);
919     TEST_SF (Val);
920     PC += 3;
921 }
922
923
924
925 static void OPC_6502_60 (void)
926 /* Opcode $60: RTS */
927 {
928     Cycles = 6;
929     PC = POP ();                /* PCL */
930     PC |= (POP () << 8);        /* PCH */
931     PC += 1;
932 }
933
934
935
936 static void OPC_6502_61 (void)
937 /* Opcode $61: ADC (zp,x) */
938 {
939     unsigned char ZPAddr;
940     unsigned Addr;
941     Cycles = 6;
942     ZPAddr = MemReadByte (PC+1) + XR;
943     Addr   = MemReadZPWord (ZPAddr);
944     ADC (MemReadByte (Addr));
945     PC += 2;
946 }
947
948
949
950 static void OPC_6502_65 (void)
951 /* Opcode $65: ADC zp */
952 {
953     unsigned char ZPAddr;
954     Cycles = 3;
955     ZPAddr = MemReadByte (PC+1);
956     ADC (MemReadByte (ZPAddr));
957     PC += 2;
958 }
959
960
961
962 static void OPC_6502_66 (void)
963 /* Opcode $66: ROR zp */
964 {
965     unsigned char ZPAddr;
966     unsigned Val;
967     Cycles = 5;
968     ZPAddr = MemReadByte (PC+1);
969     Val    = MemReadByte (ZPAddr);
970     ROR (Val);
971     MemWriteByte (ZPAddr, Val);
972     PC += 2;
973 }
974
975
976
977 static void OPC_6502_68 (void)
978 /* Opcode $68: PLA */
979 {
980     Cycles = 4;
981     AC = POP ();
982     TEST_ZF (AC);
983     TEST_SF (AC);
984     PC += 1;
985 }
986
987
988
989 static void OPC_6502_69 (void)
990 /* Opcode $69: ADC #imm */
991 {
992     Cycles = 2;
993     ADC (MemReadByte (PC+1));
994     PC += 2;
995 }
996
997
998
999 static void OPC_6502_6A (void)
1000 /* Opcode $6A: ROR a */
1001 {
1002     unsigned Val;
1003     Cycles = 2;
1004     Val = AC;
1005     ROR (Val);
1006     AC = (unsigned char) Val;
1007     PC += 1;
1008 }
1009
1010
1011
1012 static void OPC_6502_6C (void)
1013 /* Opcode $6C: JMP (ind) */
1014 {
1015     unsigned Addr;
1016     Cycles = 5;
1017     Addr = MemReadWord (PC+1);
1018     if (CPU == CPU_6502) {
1019         /* Emulate the 6502 bug */
1020         PC = MemReadByte (Addr);
1021         Addr = (Addr & 0xFF00) | ((Addr + 1) & 0xFF);
1022         PC |= (MemReadByte (Addr) << 8);
1023     } else {
1024         /* 65C02 and above have this bug fixed */
1025         PC = MemReadWord (Addr);
1026     }
1027 }
1028
1029
1030
1031 static void OPC_6502_6D (void)
1032 /* Opcode $6D: ADC abs */
1033 {
1034     unsigned Addr;
1035     Cycles = 4;
1036     Addr   = MemReadWord (PC+1);
1037     ADC (MemReadByte (Addr));
1038     PC += 3;
1039 }
1040
1041
1042
1043 static void OPC_6502_6E (void)
1044 /* Opcode $6E: ROR abs */
1045 {
1046     unsigned Addr;
1047     unsigned Val;
1048     Cycles = 6;
1049     Addr = MemReadWord (PC+1);
1050     Val  = MemReadByte (Addr);
1051     ROR (Val);
1052     MemWriteByte (Addr, Val);
1053     PC += 3;
1054 }
1055
1056
1057
1058 static void OPC_6502_70 (void)
1059 /* Opcode $70: BVS */
1060 {
1061     BRANCH (GET_OF ());
1062 }
1063
1064
1065
1066 static void OPC_6502_71 (void)
1067 /* Opcode $71: ADC (zp),y */
1068 {
1069     unsigned char ZPAddr;
1070     unsigned Addr;
1071     Cycles = 5;
1072     ZPAddr = MemReadByte (PC+1);
1073     Addr   = MemReadZPWord (ZPAddr);
1074     if (PAGE_CROSS (Addr, YR)) {
1075         ++Cycles;
1076     }
1077     ADC (MemReadByte (Addr + YR));
1078     PC += 2;
1079 }
1080
1081
1082
1083 static void OPC_6502_75 (void)
1084 /* Opcode $75: ADC zp,x */
1085 {
1086     unsigned char ZPAddr;
1087     Cycles = 4;
1088     ZPAddr = MemReadByte (PC+1) + XR;
1089     ADC (MemReadByte (ZPAddr));
1090     PC += 2;
1091 }
1092
1093
1094
1095 static void OPC_6502_76 (void)
1096 /* Opcode $76: ROR zp,x */
1097 {
1098     unsigned char ZPAddr;
1099     unsigned Val;
1100     Cycles = 6;
1101     ZPAddr = MemReadByte (PC+1) + XR;
1102     Val    = MemReadByte (ZPAddr);
1103     ROR (Val);
1104     MemWriteByte (ZPAddr, Val);
1105     PC += 2;
1106 }
1107
1108
1109
1110 static void OPC_6502_78 (void)
1111 /* Opcode $78: SEI */
1112 {
1113     Cycles = 2;
1114     SET_IF (1);
1115     PC += 1;
1116 }
1117
1118
1119
1120 static void OPC_6502_79 (void)
1121 /* Opcode $79: ADC abs,y */
1122 {
1123     unsigned Addr;
1124     Cycles = 4;
1125     Addr   = MemReadWord (PC+1);
1126     if (PAGE_CROSS (Addr, YR)) {
1127         ++Cycles;
1128     }
1129     ADC (MemReadByte (Addr + YR));
1130     PC += 3;
1131 }
1132
1133
1134
1135 static void OPC_6502_7D (void)
1136 /* Opcode $7D: ADC abs,x */
1137 {
1138     unsigned Addr;
1139     Cycles = 4;
1140     Addr   = MemReadWord (PC+1);
1141     if (PAGE_CROSS (Addr, XR)) {
1142         ++Cycles;
1143     }
1144     ADC (MemReadByte (Addr + XR));
1145     PC += 3;
1146 }
1147
1148
1149
1150 static void OPC_6502_7E (void)
1151 /* Opcode $7E: ROR abs,x */
1152 {
1153     unsigned Addr;
1154     unsigned Val;
1155     Cycles = 7;
1156     Addr = MemReadByte (PC+1) + XR;
1157     Val  = MemReadByte (Addr);
1158     ROR (Val);
1159     MemWriteByte (Addr, Val);
1160     PC += 3;
1161 }
1162
1163
1164
1165 static void OPC_6502_81 (void)
1166 /* Opcode $81: STA (zp,x) */
1167 {
1168     unsigned char ZPAddr;
1169     unsigned Addr;
1170     Cycles = 6;
1171     ZPAddr = MemReadByte (PC+1) + XR;
1172     Addr   = MemReadZPWord (ZPAddr);
1173     MemWriteByte (Addr, AC);
1174     PC += 2;
1175 }
1176
1177
1178
1179 static void OPC_6502_84 (void)
1180 /* Opcode $84: STY zp */
1181 {
1182     unsigned char ZPAddr;
1183     Cycles = 3;
1184     ZPAddr = MemReadByte (PC+1);
1185     MemWriteByte (ZPAddr, YR);
1186     PC += 2;
1187 }
1188
1189
1190
1191 static void OPC_6502_85 (void)
1192 /* Opcode $85: STA zp */
1193 {
1194     unsigned char ZPAddr;
1195     Cycles = 3;
1196     ZPAddr = MemReadByte (PC+1);
1197     MemWriteByte (ZPAddr, AC);
1198     PC += 2;
1199 }
1200
1201
1202
1203 static void OPC_6502_86 (void)
1204 /* Opcode $86: STX zp */
1205 {
1206     unsigned char ZPAddr;
1207     Cycles = 3;
1208     ZPAddr = MemReadByte (PC+1);
1209     MemWriteByte (ZPAddr, XR);
1210     PC += 2;
1211 }
1212
1213
1214
1215 static void OPC_6502_88 (void)
1216 /* Opcode $88: DEY */
1217 {
1218     Cycles = 2;
1219     --YR;
1220     TEST_ZF (YR);
1221     TEST_SF (YR);
1222     PC += 1;
1223 }
1224
1225
1226
1227 static void OPC_6502_8A (void)
1228 /* Opcode $8A: TXA */
1229 {
1230     Cycles = 2;
1231     AC = XR;
1232     TEST_ZF (AC);
1233     TEST_SF (AC);
1234     PC += 1;
1235 }
1236
1237
1238
1239 static void OPC_6502_8C (void)
1240 /* Opcode $8C: STY abs */
1241 {
1242     unsigned Addr;
1243     Cycles = 4;
1244     Addr = MemReadWord (PC+1);
1245     MemWriteByte (Addr, YR);
1246     PC += 3;
1247 }
1248
1249
1250
1251 static void OPC_6502_8D (void)
1252 /* Opcode $8D: STA abs */
1253 {
1254     unsigned Addr;
1255     Cycles = 4;
1256     Addr = MemReadWord (PC+1);
1257     MemWriteByte (Addr, AC);
1258     PC += 3;
1259 }
1260
1261
1262
1263 static void OPC_6502_8E (void)
1264 /* Opcode $8E: STX abs */
1265 {
1266     unsigned Addr;
1267     Cycles = 4;
1268     Addr = MemReadWord (PC+1);
1269     MemWriteByte (Addr, XR);
1270     PC += 3;
1271 }
1272
1273
1274
1275 static void OPC_6502_90 (void)
1276 /* Opcode $90: BCC */
1277 {
1278     BRANCH (!GET_CF ());
1279 }
1280
1281
1282
1283 static void OPC_6502_91 (void)
1284 /* Opcode $91: sta (zp),y */
1285 {
1286     unsigned char ZPAddr;
1287     unsigned Addr;
1288     Cycles = 6;
1289     ZPAddr = MemReadByte (PC+1);
1290     Addr   = MemReadZPWord (ZPAddr) + YR;
1291     MemWriteByte (Addr, AC);
1292     PC += 2;
1293 }
1294
1295
1296
1297 static void OPC_6502_94 (void)
1298 /* Opcode $94: STY zp,x */
1299 {
1300     unsigned char ZPAddr;
1301     Cycles = 4;
1302     ZPAddr = MemReadByte (PC+1) + XR;
1303     MemWriteByte (ZPAddr, YR);
1304     PC += 2;
1305 }
1306
1307
1308
1309 static void OPC_6502_95 (void)
1310 /* Opcode $95: STA zp,x */
1311 {
1312     unsigned char ZPAddr;
1313     Cycles = 4;
1314     ZPAddr = MemReadByte (PC+1) + XR;
1315     MemWriteByte (ZPAddr, AC);
1316     PC += 2;
1317 }
1318
1319
1320
1321 static void OPC_6502_96 (void)
1322 /* Opcode $96: stx zp,y */
1323 {
1324     unsigned char ZPAddr;
1325     Cycles = 4;
1326     ZPAddr = MemReadByte (PC+1) + YR;
1327     MemWriteByte (ZPAddr, XR);
1328     PC += 2;
1329 }
1330
1331
1332
1333 static void OPC_6502_98 (void)
1334 /* Opcode $98: TYA */
1335 {
1336     Cycles = 2;
1337     AC = YR;
1338     TEST_ZF (AC);
1339     TEST_SF (AC);
1340     PC += 1;
1341 }
1342
1343
1344
1345 static void OPC_6502_99 (void)
1346 /* Opcode $99: STA abs,y */
1347 {
1348     unsigned Addr;
1349     Cycles = 5;
1350     Addr   = MemReadWord (PC+1) + YR;
1351     MemWriteByte (Addr, AC);
1352     PC += 3;
1353 }
1354
1355
1356
1357 static void OPC_6502_9A (void)
1358 /* Opcode $9A: TXS */
1359 {
1360     Cycles = 2;
1361     SP = XR;
1362     PC += 1;
1363 }
1364
1365
1366
1367 static void OPC_6502_9D (void)
1368 /* Opcode $9D: STA abs,x */
1369 {
1370     unsigned Addr;
1371     Cycles = 5;
1372     Addr   = MemReadWord (PC+1) + XR;
1373     MemWriteByte (Addr, AC);
1374     PC += 3;
1375 }
1376
1377
1378
1379 static void OPC_6502_A0 (void)
1380 /* Opcode $A0: LDY #imm */
1381 {
1382     Cycles = 2;
1383     YR = MemReadByte (PC+1);
1384     TEST_ZF (YR);
1385     TEST_SF (YR);
1386     PC += 2;
1387 }
1388
1389
1390
1391 static void OPC_6502_A1 (void)
1392 /* Opcode $A1: LDA (zp,x) */
1393 {
1394     unsigned char ZPAddr;
1395     unsigned Addr;
1396     Cycles = 6;
1397     ZPAddr = MemReadByte (PC+1) + XR;
1398     Addr = MemReadZPWord (ZPAddr);
1399     AC = MemReadByte (Addr);
1400     TEST_ZF (AC);
1401     TEST_SF (AC);
1402     PC += 2;
1403 }
1404
1405
1406
1407 static void OPC_6502_A2 (void)
1408 /* Opcode $A2: LDX #imm */
1409 {
1410     Cycles = 2;
1411     XR = MemReadByte (PC+1);
1412     TEST_ZF (XR);
1413     TEST_SF (XR);
1414     PC += 2;
1415 }
1416
1417
1418
1419 static void OPC_6502_A4 (void)
1420 /* Opcode $A4: LDY zp */
1421 {
1422     unsigned char ZPAddr;
1423     Cycles = 3;
1424     ZPAddr = MemReadByte (PC+1);
1425     YR = MemReadByte (ZPAddr);
1426     TEST_ZF (YR);
1427     TEST_SF (YR);
1428     PC += 2;
1429 }
1430
1431
1432
1433 static void OPC_6502_A5 (void)
1434 /* Opcode $A5: LDA zp */
1435 {
1436     unsigned char ZPAddr;
1437     Cycles = 3;
1438     ZPAddr = MemReadByte (PC+1);
1439     AC = MemReadByte (ZPAddr);
1440     TEST_ZF (AC);
1441     TEST_SF (AC);
1442     PC += 2;
1443 }
1444
1445
1446
1447 static void OPC_6502_A6 (void)
1448 /* Opcode $A6: LDX zp */
1449 {
1450     unsigned char ZPAddr;
1451     Cycles = 3;
1452     ZPAddr = MemReadByte (PC+1);
1453     XR = MemReadByte (ZPAddr);
1454     TEST_ZF (XR);
1455     TEST_SF (XR);
1456     PC += 2;
1457 }
1458
1459
1460
1461 static void OPC_6502_A8 (void)
1462 /* Opcode $A8: TAY */
1463 {
1464     Cycles = 2;
1465     YR = AC;
1466     TEST_ZF (YR);
1467     TEST_SF (YR);
1468     PC += 1;
1469 }
1470
1471
1472
1473 static void OPC_6502_A9 (void)
1474 /* Opcode $A9: LDA #imm */
1475 {
1476     Cycles = 2;
1477     AC = MemReadByte (PC+1);
1478     TEST_ZF (AC);
1479     TEST_SF (AC);
1480     PC += 2;
1481 }
1482
1483
1484
1485 static void OPC_6502_AA (void)
1486 /* Opcode $AA: TAX */
1487 {
1488     Cycles = 2;
1489     XR = AC;
1490     TEST_ZF (XR);
1491     TEST_SF (XR);
1492     PC += 1;
1493 }
1494
1495
1496
1497 static void OPC_6502_AC (void)
1498 /* Opcode $AC: LDY abs */
1499 {
1500     unsigned Addr;
1501     Cycles = 4;
1502     Addr   = MemReadWord (PC+1);
1503     YR     = MemReadByte (Addr);
1504     TEST_ZF (YR);
1505     TEST_SF (YR);
1506     PC += 3;
1507 }
1508
1509
1510
1511 static void OPC_6502_AD (void)
1512 /* Opcode $AD: LDA abs */
1513 {
1514     unsigned Addr;
1515     Cycles = 4;
1516     Addr   = MemReadWord (PC+1);
1517     AC     = MemReadByte (Addr);
1518     TEST_ZF (AC);
1519     TEST_SF (AC);
1520     PC += 3;
1521 }
1522
1523
1524
1525 static void OPC_6502_AE (void)
1526 /* Opcode $AE: LDX abs */
1527 {
1528     unsigned Addr;
1529     Cycles = 4;
1530     Addr   = MemReadWord (PC+1);
1531     XR     = MemReadByte (Addr);
1532     TEST_ZF (XR);
1533     TEST_SF (XR);
1534     PC += 3;
1535 }
1536
1537
1538
1539 static void OPC_6502_B0 (void)
1540 /* Opcode $B0: BCS */
1541 {
1542     BRANCH (GET_CF ());
1543 }
1544
1545
1546
1547 static void OPC_6502_B1 (void)
1548 /* Opcode $B1: LDA (zp),y */
1549 {
1550     unsigned char ZPAddr;
1551     unsigned Addr;
1552     Cycles = 5;
1553     ZPAddr = MemReadByte (PC+1);
1554     Addr   = MemReadZPWord (ZPAddr);
1555     if (PAGE_CROSS (Addr, YR)) {
1556         ++Cycles;
1557     }
1558     AC = MemReadByte (Addr + YR);
1559     TEST_ZF (AC);
1560     TEST_SF (AC);
1561     PC += 2;
1562 }
1563
1564
1565
1566 static void OPC_6502_B4 (void)
1567 /* Opcode $B4: LDY zp,x */
1568 {
1569     unsigned char ZPAddr;
1570     Cycles = 4;
1571     ZPAddr = MemReadByte (PC+1) + XR;
1572     YR     = MemReadByte (ZPAddr);
1573     TEST_ZF (YR);
1574     TEST_SF (YR);
1575     PC += 2;
1576 }
1577
1578
1579
1580 static void OPC_6502_B5 (void)
1581 /* Opcode $B5: LDA zp,x */
1582 {
1583     unsigned char ZPAddr;
1584     Cycles = 4;
1585     ZPAddr = MemReadByte (PC+1) + XR;
1586     AC     = MemReadByte (ZPAddr);
1587     TEST_ZF (AC);
1588     TEST_SF (AC);
1589     PC += 2;
1590 }
1591
1592
1593
1594 static void OPC_6502_B6 (void)
1595 /* Opcode $B6: LDX zp,y */
1596 {
1597     unsigned char ZPAddr;
1598     Cycles = 4;
1599     ZPAddr = MemReadByte (PC+1) + YR;
1600     XR     = MemReadByte (ZPAddr);
1601     TEST_ZF (XR);
1602     TEST_SF (XR);
1603     PC += 2;
1604 }
1605
1606
1607
1608 static void OPC_6502_B8 (void)
1609 /* Opcode $B8: CLV */
1610 {
1611     Cycles = 2;
1612     SET_OF (0);
1613     PC += 1;
1614 }
1615
1616
1617
1618 static void OPC_6502_B9 (void)
1619 /* Opcode $B9: LDA abs,y */
1620 {
1621     unsigned Addr;
1622     Cycles = 4;
1623     Addr = MemReadWord (PC+1);
1624     if (PAGE_CROSS (Addr, YR)) {
1625         ++Cycles;
1626     }
1627     AC = MemReadByte (Addr + YR);
1628     TEST_ZF (AC);
1629     TEST_SF (AC);
1630     PC += 3;
1631 }
1632
1633
1634
1635 static void OPC_6502_BA (void)
1636 /* Opcode $BA: TSX */
1637 {
1638     Cycles = 2;
1639     XR = SP;
1640     TEST_ZF (XR);
1641     TEST_SF (XR);
1642     PC += 1;
1643 }
1644
1645
1646
1647 static void OPC_6502_BC (void)
1648 /* Opcode $BC: LDY abs,x */
1649 {
1650     unsigned Addr;
1651     Cycles = 4;
1652     Addr = MemReadWord (PC+1);
1653     if (PAGE_CROSS (Addr, XR)) {
1654         ++Cycles;
1655     }
1656     YR = MemReadByte (Addr + XR);
1657     TEST_ZF (YR);
1658     TEST_SF (YR);
1659     PC += 3;
1660 }
1661
1662
1663
1664 static void OPC_6502_BD (void)
1665 /* Opcode $BD: LDA abs,x */
1666 {
1667     unsigned Addr;
1668     Cycles = 4;
1669     Addr = MemReadWord (PC+1);
1670     if (PAGE_CROSS (Addr, XR)) {
1671         ++Cycles;
1672     }
1673     AC = MemReadByte (Addr + XR);
1674     TEST_ZF (AC);
1675     TEST_SF (AC);
1676     PC += 3;
1677 }
1678
1679
1680
1681 static void OPC_6502_BE (void)
1682 /* Opcode $BE: LDX abs,y */
1683 {
1684     unsigned Addr;
1685     Cycles = 4;
1686     Addr = MemReadWord (PC+1);
1687     if (PAGE_CROSS (Addr, YR)) {
1688         ++Cycles;
1689     }
1690     XR = MemReadByte (Addr + YR);
1691     TEST_ZF (XR);
1692     TEST_SF (XR);
1693     PC += 3;
1694 }
1695
1696
1697
1698 static void OPC_6502_C0 (void)
1699 /* Opcode $C0: CPY #imm */
1700 {
1701     Cycles = 2;
1702     CMP (YR, MemReadByte (PC+1));
1703     PC += 2;
1704 }
1705
1706
1707
1708 static void OPC_6502_C1 (void)
1709 /* Opcode $C1: CMP (zp,x) */
1710 {
1711     unsigned char ZPAddr;
1712     unsigned Addr;
1713     Cycles = 6;
1714     ZPAddr = MemReadByte (PC+1) + XR;
1715     Addr   = MemReadZPWord (ZPAddr);
1716     CMP (AC, MemReadByte (Addr));
1717     PC += 2;
1718 }
1719
1720
1721
1722 static void OPC_6502_C4 (void)
1723 /* Opcode $C4: CPY zp */
1724 {
1725     unsigned char ZPAddr;
1726     Cycles = 3;
1727     ZPAddr = MemReadByte (PC+1);
1728     CMP (YR, MemReadByte (ZPAddr));
1729     PC += 2;
1730 }
1731
1732
1733
1734 static void OPC_6502_C5 (void)
1735 /* Opcode $C5: CMP zp */
1736 {
1737     unsigned char ZPAddr;
1738     Cycles = 3;
1739     ZPAddr = MemReadByte (PC+1);
1740     CMP (AC, MemReadByte (ZPAddr));
1741     PC += 2;
1742 }
1743
1744
1745
1746 static void OPC_6502_C6 (void)
1747 /* Opcode $C6: DEC zp */
1748 {
1749     unsigned char ZPAddr;
1750     unsigned char Val;
1751     Cycles = 5;
1752     ZPAddr = MemReadByte (PC+1);
1753     Val    = MemReadByte (ZPAddr) - 1;
1754     MemWriteByte (ZPAddr, Val);
1755     TEST_ZF (Val);
1756     TEST_SF (Val);
1757     PC += 2;
1758 }
1759
1760
1761
1762 static void OPC_6502_C8 (void)
1763 /* Opcode $C8: INY */
1764 {
1765     Cycles = 2;
1766     ++YR;
1767     TEST_ZF (YR);
1768     TEST_SF (YR);
1769     PC += 1;
1770 }
1771
1772
1773
1774 static void OPC_6502_C9 (void)
1775 /* Opcode $C9: CMP #imm */
1776 {
1777     Cycles = 2;
1778     CMP (AC, MemReadByte (PC+1));
1779     PC += 2;
1780 }
1781
1782
1783
1784 static void OPC_6502_CA (void)
1785 /* Opcode $CA: DEX */
1786 {
1787     Cycles = 2;
1788     --XR;
1789     TEST_ZF (XR);
1790     TEST_SF (XR);
1791     PC += 1;
1792 }
1793
1794
1795
1796 static void OPC_6502_CC (void)
1797 /* Opcode $CC: CPY abs */
1798 {
1799     unsigned Addr;
1800     Cycles = 4;
1801     Addr   = MemReadWord (PC+1);
1802     CMP (YR, MemReadByte (Addr));
1803     PC += 3;
1804 }
1805
1806
1807
1808 static void OPC_6502_CD (void)
1809 /* Opcode $CD: CMP abs */
1810 {
1811     unsigned Addr;
1812     Cycles = 4;
1813     Addr   = MemReadWord (PC+1);
1814     CMP (AC, MemReadByte (Addr));
1815     PC += 3;
1816 }
1817
1818
1819
1820 static void OPC_6502_CE (void)
1821 /* Opcode $CE: DEC abs */
1822 {
1823     unsigned Addr;
1824     unsigned char Val;
1825     Cycles = 6;
1826     Addr = MemReadWord (PC+1);
1827     Val  = MemReadByte (Addr) - 1;
1828     MemWriteByte (Addr, Val);
1829     TEST_ZF (Val);
1830     TEST_SF (Val);
1831     PC += 3;
1832 }
1833
1834
1835
1836 static void OPC_6502_D0 (void)
1837 /* Opcode $D0: BNE */
1838 {
1839     BRANCH (!GET_ZF ());
1840 }
1841
1842
1843
1844 static void OPC_6502_D1 (void)
1845 /* Opcode $D1: CMP (zp),y */
1846 {
1847     unsigned ZPAddr;
1848     unsigned Addr;
1849     Cycles = 5;
1850     ZPAddr = MemReadByte (PC+1);
1851     Addr   = MemReadWord (ZPAddr);
1852     if (PAGE_CROSS (Addr, YR)) {
1853         ++Cycles;
1854     }
1855     CMP (AC, MemReadByte (Addr + YR));
1856     PC += 2;
1857 }
1858
1859
1860
1861 static void OPC_6502_D5 (void)
1862 /* Opcode $D5: CMP zp,x */
1863 {
1864     unsigned char ZPAddr;
1865     Cycles = 4;
1866     ZPAddr = MemReadByte (PC+1) + XR;
1867     CMP (AC, MemReadByte (ZPAddr));
1868     PC += 2;
1869 }
1870
1871
1872
1873 static void OPC_6502_D6 (void)
1874 /* Opcode $D6: DEC zp,x */
1875 {
1876     unsigned char ZPAddr;
1877     unsigned char Val;
1878     Cycles = 6;
1879     ZPAddr = MemReadByte (PC+1) + XR;
1880     Val  = MemReadByte (ZPAddr) - 1;
1881     MemWriteByte (ZPAddr, Val);
1882     TEST_ZF (Val);
1883     TEST_SF (Val);
1884     PC += 2;
1885 }
1886
1887
1888
1889 static void OPC_6502_D8 (void)
1890 /* Opcode $D8: CLD */
1891 {
1892     Cycles = 2;
1893     SET_DF (0);
1894     PC += 1;
1895 }
1896
1897
1898
1899 static void OPC_6502_D9 (void)
1900 /* Opcode $D9: CMP abs,y */
1901 {
1902     unsigned Addr;
1903     Cycles = 4;
1904     Addr = MemReadWord (PC+1);
1905     if (PAGE_CROSS (Addr, YR)) {
1906         ++Cycles;
1907     }
1908     CMP (AC, MemReadByte (Addr + YR));
1909     PC += 3;
1910 }
1911
1912
1913
1914 static void OPC_6502_DD (void)
1915 /* Opcode $DD: CMP abs,x */
1916 {
1917     unsigned Addr;
1918     Cycles = 4;
1919     Addr = MemReadWord (PC+1);
1920     if (PAGE_CROSS (Addr, XR)) {
1921         ++Cycles;
1922     }
1923     CMP (AC, MemReadByte (Addr + XR));
1924     PC += 3;
1925 }
1926
1927
1928
1929 static void OPC_6502_DE (void)
1930 /* Opcode $DE: DEC abs,x */
1931 {
1932     unsigned Addr;
1933     unsigned char Val;
1934     Cycles = 7;
1935     Addr = MemReadWord (PC+1) + XR;
1936     Val  = MemReadByte (Addr) - 1;
1937     MemWriteByte (Addr, Val);
1938     TEST_ZF (Val);
1939     TEST_SF (Val);
1940     PC += 3;
1941 }
1942
1943
1944
1945 static void OPC_6502_E0 (void)
1946 /* Opcode $E0: CPX #imm */
1947 {
1948     Cycles = 2;
1949     CMP (XR, MemReadByte (PC+1));
1950     PC += 2;
1951 }
1952
1953
1954
1955 static void OPC_6502_E1 (void)
1956 /* Opcode $E1: SBC (zp,x) */
1957 {
1958     unsigned char ZPAddr;
1959     unsigned Addr;
1960     Cycles = 6;
1961     ZPAddr = MemReadByte (PC+1) + XR;
1962     Addr   = MemReadZPWord (ZPAddr);
1963     SBC (MemReadByte (Addr));
1964     PC += 2;
1965 }
1966
1967
1968
1969 static void OPC_6502_E4 (void)
1970 /* Opcode $E4: CPX zp */
1971 {
1972     unsigned char ZPAddr;
1973     Cycles = 3;
1974     ZPAddr = MemReadByte (PC+1);
1975     CMP (XR, MemReadByte (ZPAddr));
1976     PC += 2;
1977 }
1978
1979
1980
1981 static void OPC_6502_E5 (void)
1982 /* Opcode $E5: SBC zp */
1983 {
1984     unsigned char ZPAddr;
1985     Cycles = 3;
1986     ZPAddr = MemReadByte (PC+1);
1987     SBC (MemReadByte (ZPAddr));
1988     PC += 2;
1989 }
1990
1991
1992
1993 static void OPC_6502_E6 (void)
1994 /* Opcode $E6: INC zp */
1995 {
1996     unsigned char ZPAddr;
1997     unsigned char Val;
1998     Cycles = 5;
1999     ZPAddr = MemReadByte (PC+1);
2000     Val    = MemReadByte (ZPAddr) + 1;
2001     MemWriteByte (ZPAddr, Val);
2002     TEST_ZF (Val);
2003     TEST_SF (Val);
2004     PC += 2;
2005 }
2006
2007
2008
2009 static void OPC_6502_E8 (void)
2010 /* Opcode $E8: INX */
2011 {
2012     Cycles = 2;
2013     ++XR;
2014     TEST_ZF (XR);
2015     TEST_SF (XR);
2016     PC += 1;
2017 }
2018
2019
2020
2021 static void OPC_6502_E9 (void)
2022 /* Opcode $E9: SBC #imm */
2023 {
2024     Cycles = 2;
2025     SBC (MemReadByte (PC+1));
2026     PC += 2;
2027 }
2028
2029
2030
2031 static void OPC_6502_EA (void)
2032 /* Opcode $EA: NOP */
2033 {
2034     /* This one is easy... */
2035     Cycles = 2;
2036     PC += 1;
2037 }
2038
2039
2040
2041 static void OPC_6502_EC (void)
2042 /* Opcode $EC: CPX abs */
2043 {
2044     unsigned Addr;
2045     Cycles = 4;
2046     Addr   = MemReadWord (PC+1);
2047     CMP (XR, MemReadByte (Addr));
2048     PC += 3;
2049 }
2050
2051
2052
2053 static void OPC_6502_ED (void)
2054 /* Opcode $ED: SBC abs */
2055 {
2056     unsigned Addr;
2057     Cycles = 4;
2058     Addr   = MemReadWord (PC+1);
2059     SBC (MemReadByte (Addr));
2060     PC += 3;
2061 }
2062
2063
2064
2065 static void OPC_6502_EE (void)
2066 /* Opcode $EE: INC abs */
2067 {
2068     unsigned Addr;
2069     unsigned char Val;
2070     Cycles = 6;
2071     Addr = MemReadWord (PC+1);
2072     Val  = MemReadByte (Addr) + 1;
2073     MemWriteByte (Addr, Val);
2074     TEST_ZF (Val);
2075     TEST_SF (Val);
2076     PC += 3;
2077 }
2078
2079
2080
2081 static void OPC_6502_F0 (void)
2082 /* Opcode $F0: BEQ */
2083 {
2084     BRANCH (GET_ZF ());
2085 }
2086
2087
2088
2089 static void OPC_6502_F1 (void)
2090 /* Opcode $F1: SBC (zp),y */
2091 {
2092     unsigned char ZPAddr;
2093     unsigned Addr;
2094     Cycles = 5;
2095     ZPAddr = MemReadByte (PC+1);
2096     Addr   = MemReadZPWord (ZPAddr);
2097     if (PAGE_CROSS (Addr, YR)) {
2098         ++Cycles;
2099     }
2100     SBC (MemReadByte (Addr + YR));
2101     PC += 2;
2102 }
2103
2104
2105
2106 static void OPC_6502_F5 (void)
2107 /* Opcode $F5: SBC zp,x */
2108 {
2109     unsigned char ZPAddr;
2110     Cycles = 4;
2111     ZPAddr = MemReadByte (PC+1) + XR;
2112     SBC (MemReadByte (ZPAddr));
2113     PC += 2;
2114 }
2115
2116
2117
2118 static void OPC_6502_F6 (void)
2119 /* Opcode $F6: INC zp,x */
2120 {
2121     unsigned char ZPAddr;
2122     unsigned char Val;
2123     Cycles = 6;
2124     ZPAddr = MemReadByte (PC+1) + XR;
2125     Val  = MemReadByte (ZPAddr) + 1;
2126     MemWriteByte (ZPAddr, Val);
2127     TEST_ZF (Val);
2128     TEST_SF (Val);
2129     PC += 2;
2130 }
2131
2132
2133
2134 static void OPC_6502_F8 (void)
2135 /* Opcode $F8: SED */
2136 {
2137     SET_DF (1);
2138 }
2139
2140
2141
2142 static void OPC_6502_F9 (void)
2143 /* Opcode $F9: SBC abs,y */
2144 {
2145     unsigned Addr;
2146     Cycles = 4;
2147     Addr   = MemReadWord (PC+1);
2148     if (PAGE_CROSS (Addr, YR)) {
2149         ++Cycles;
2150     }
2151     SBC (MemReadByte (Addr + YR));
2152     PC += 3;
2153 }
2154
2155
2156
2157 static void OPC_6502_FD (void)
2158 /* Opcode $FD: SBC abs,x */
2159 {
2160     unsigned Addr;
2161     Cycles = 4;
2162     Addr   = MemReadWord (PC+1);
2163     if (PAGE_CROSS (Addr, XR)) {
2164         ++Cycles;
2165     }
2166     SBC (MemReadByte (Addr + XR));
2167     PC += 3;
2168 }
2169
2170
2171
2172 static void OPC_6502_FE (void)
2173 /* Opcode $FE: INC abs,x */
2174 {
2175     unsigned Addr;
2176     unsigned char Val;
2177     Cycles = 7;
2178     Addr = MemReadWord (PC+1) + XR;
2179     Val  = MemReadByte (Addr) + 1;
2180     MemWriteByte (Addr, Val);
2181     TEST_ZF (Val);
2182     TEST_SF (Val);
2183     PC += 3;
2184 }
2185
2186
2187
2188 /*****************************************************************************/
2189 /*                                   Data                                    */
2190 /*****************************************************************************/
2191
2192
2193
2194 /* Opcode handler table */
2195 typedef void (*OPCFunc) (void);
2196 static OPCFunc OPCTable[256] = {
2197     OPC_6502_00,
2198     OPC_6502_01,
2199     OPC_Illegal,
2200     OPC_Illegal,
2201     OPC_Illegal,
2202     OPC_6502_05,
2203     OPC_6502_06,
2204     OPC_Illegal,
2205     OPC_6502_08,
2206     OPC_6502_09,
2207     OPC_6502_0A,
2208     OPC_Illegal,
2209     OPC_Illegal,
2210     OPC_6502_0D,
2211     OPC_6502_0E,
2212     OPC_Illegal,
2213     OPC_6502_10,
2214     OPC_6502_11,
2215     OPC_Illegal,
2216     OPC_Illegal,
2217     OPC_Illegal,
2218     OPC_6502_15,
2219     OPC_6502_16,
2220     OPC_Illegal,
2221     OPC_6502_18,
2222     OPC_6502_19,
2223     OPC_Illegal,
2224     OPC_Illegal,
2225     OPC_Illegal,
2226     OPC_6502_1D,
2227     OPC_6502_1E,
2228     OPC_Illegal,
2229     OPC_6502_20,
2230     OPC_6502_21,
2231     OPC_Illegal,
2232     OPC_Illegal,
2233     OPC_6502_24,
2234     OPC_6502_25,
2235     OPC_6502_26,
2236     OPC_Illegal,
2237     OPC_6502_28,
2238     OPC_6502_29,
2239     OPC_6502_2A,
2240     OPC_Illegal,
2241     OPC_6502_2C,
2242     OPC_6502_2D,
2243     OPC_6502_2E,
2244     OPC_Illegal,
2245     OPC_6502_30,
2246     OPC_6502_31,
2247     OPC_Illegal,
2248     OPC_Illegal,
2249     OPC_Illegal,
2250     OPC_6502_35,
2251     OPC_6502_36,
2252     OPC_Illegal,
2253     OPC_6502_38,
2254     OPC_6502_39,
2255     OPC_Illegal,
2256     OPC_Illegal,
2257     OPC_Illegal,
2258     OPC_6502_3D,
2259     OPC_6502_3E,
2260     OPC_Illegal,
2261     OPC_6502_40,
2262     OPC_6502_41,
2263     OPC_Illegal,
2264     OPC_Illegal,
2265     OPC_Illegal,
2266     OPC_6502_45,
2267     OPC_6502_46,
2268     OPC_Illegal,
2269     OPC_6502_48,
2270     OPC_6502_49,
2271     OPC_6502_4A,
2272     OPC_Illegal,
2273     OPC_6502_4C,
2274     OPC_6502_4D,
2275     OPC_6502_4E,
2276     OPC_Illegal,
2277     OPC_6502_50,
2278     OPC_6502_51,
2279     OPC_Illegal,
2280     OPC_Illegal,
2281     OPC_Illegal,
2282     OPC_6502_55,
2283     OPC_6502_56,
2284     OPC_Illegal,
2285     OPC_6502_58,
2286     OPC_6502_59,
2287     OPC_Illegal,
2288     OPC_Illegal,
2289     OPC_Illegal,
2290     OPC_6502_5D,
2291     OPC_6502_5E,
2292     OPC_Illegal,
2293     OPC_6502_60,
2294     OPC_6502_61,
2295     OPC_Illegal,
2296     OPC_Illegal,
2297     OPC_Illegal,
2298     OPC_6502_65,
2299     OPC_6502_66,
2300     OPC_Illegal,
2301     OPC_6502_68,
2302     OPC_6502_69,
2303     OPC_6502_6A,
2304     OPC_Illegal,
2305     OPC_6502_6C,
2306     OPC_6502_6D,
2307     OPC_6502_6E,
2308     OPC_Illegal,
2309     OPC_6502_70,
2310     OPC_6502_71,
2311     OPC_Illegal,
2312     OPC_Illegal,
2313     OPC_Illegal,
2314     OPC_6502_75,
2315     OPC_6502_76,
2316     OPC_Illegal,
2317     OPC_6502_78,
2318     OPC_6502_79,
2319     OPC_Illegal,
2320     OPC_Illegal,
2321     OPC_Illegal,
2322     OPC_6502_7D,
2323     OPC_6502_7E,
2324     OPC_Illegal,
2325     OPC_Illegal,
2326     OPC_6502_81,
2327     OPC_Illegal,
2328     OPC_Illegal,
2329     OPC_6502_84,
2330     OPC_6502_85,
2331     OPC_6502_86,
2332     OPC_Illegal,
2333     OPC_6502_88,
2334     OPC_Illegal,
2335     OPC_6502_8A,
2336     OPC_Illegal,
2337     OPC_6502_8C,
2338     OPC_6502_8D,
2339     OPC_6502_8E,
2340     OPC_Illegal,
2341     OPC_6502_90,
2342     OPC_6502_91,
2343     OPC_Illegal,
2344     OPC_Illegal,
2345     OPC_6502_94,
2346     OPC_6502_95,
2347     OPC_6502_96,
2348     OPC_Illegal,
2349     OPC_6502_98,
2350     OPC_6502_99,
2351     OPC_6502_9A,
2352     OPC_Illegal,
2353     OPC_Illegal,
2354     OPC_6502_9D,
2355     OPC_Illegal,
2356     OPC_Illegal,
2357     OPC_6502_A0,
2358     OPC_6502_A1,
2359     OPC_6502_A2,
2360     OPC_Illegal,
2361     OPC_6502_A4,
2362     OPC_6502_A5,
2363     OPC_6502_A6,
2364     OPC_Illegal,
2365     OPC_6502_A8,
2366     OPC_6502_A9,
2367     OPC_6502_AA,
2368     OPC_Illegal,
2369     OPC_6502_AC,
2370     OPC_6502_AD,
2371     OPC_6502_AE,
2372     OPC_Illegal,
2373     OPC_6502_B0,
2374     OPC_6502_B1,
2375     OPC_Illegal,
2376     OPC_Illegal,
2377     OPC_6502_B4,
2378     OPC_6502_B5,
2379     OPC_6502_B6,
2380     OPC_Illegal,
2381     OPC_6502_B8,
2382     OPC_6502_B9,
2383     OPC_6502_BA,
2384     OPC_Illegal,
2385     OPC_6502_BC,
2386     OPC_6502_BD,
2387     OPC_6502_BE,
2388     OPC_Illegal,
2389     OPC_6502_C0,
2390     OPC_6502_C1,
2391     OPC_Illegal,
2392     OPC_Illegal,
2393     OPC_6502_C4,
2394     OPC_6502_C5,
2395     OPC_6502_C6,
2396     OPC_Illegal,
2397     OPC_6502_C8,
2398     OPC_6502_C9,
2399     OPC_6502_CA,
2400     OPC_Illegal,
2401     OPC_6502_CC,
2402     OPC_6502_CD,
2403     OPC_6502_CE,
2404     OPC_Illegal,
2405     OPC_6502_D0,
2406     OPC_6502_D1,
2407     OPC_Illegal,
2408     OPC_Illegal,
2409     OPC_Illegal,
2410     OPC_6502_D5,
2411     OPC_6502_D6,
2412     OPC_Illegal,
2413     OPC_6502_D8,
2414     OPC_6502_D9,
2415     OPC_Illegal,
2416     OPC_Illegal,
2417     OPC_Illegal,
2418     OPC_6502_DD,
2419     OPC_6502_DE,
2420     OPC_Illegal,
2421     OPC_6502_E0,
2422     OPC_6502_E1,
2423     OPC_Illegal,
2424     OPC_Illegal,
2425     OPC_6502_E4,
2426     OPC_6502_E5,
2427     OPC_6502_E6,
2428     OPC_Illegal,
2429     OPC_6502_E8,
2430     OPC_6502_E9,
2431     OPC_6502_EA,
2432     OPC_Illegal,
2433     OPC_6502_EC,
2434     OPC_6502_ED,
2435     OPC_6502_EE,
2436     OPC_Illegal,
2437     OPC_6502_F0,
2438     OPC_6502_F1,
2439     OPC_Illegal,
2440     OPC_Illegal,
2441     OPC_Illegal,
2442     OPC_6502_F5,
2443     OPC_6502_F6,
2444     OPC_Illegal,
2445     OPC_6502_F8,
2446     OPC_6502_F9,
2447     OPC_Illegal,
2448     OPC_Illegal,
2449     OPC_Illegal,
2450     OPC_6502_FD,
2451     OPC_6502_FE,
2452     OPC_Illegal,
2453 };
2454
2455
2456
2457 /*****************************************************************************/
2458 /*                                   Code                                    */
2459 /*****************************************************************************/
2460
2461
2462
2463 void CPUInit (void)
2464 /* Initialize the CPU */
2465 {
2466     PC = MemReadWord (0xFFFC);
2467 }
2468
2469
2470
2471 void Reset (void)
2472 /* Reset the CPU */
2473 {
2474 }
2475
2476
2477
2478 void IRQ (void)
2479 /* Generate an IRQ */
2480 {
2481 }
2482
2483
2484
2485 void NMI (void)
2486 /* Generate an NMI */
2487 {
2488 }
2489
2490
2491
2492 void CPURun (void)
2493 /* Run the CPU */
2494 {
2495     while (!CPUHalted) {
2496
2497         /* Get the next opcode */
2498         unsigned char OPC = MemReadByte (PC);
2499
2500         printf ("%6lu %04X %02X A=%02X X=%02X Y=%02X %c%c%c%c%c%c%c\n",
2501                 TotalCycles, PC, OPC, AC, XR, YR,
2502                 GET_SF()? 'S' : '-',
2503                 GET_ZF()? 'Z' : '-',
2504                 GET_CF()? 'C' : '-',
2505                 GET_IF()? 'I' : '-',
2506                 GET_BF()? 'B' : '-',
2507                 GET_DF()? 'D' : '-',
2508                 GET_OF()? 'V' : '-');
2509
2510         /* Execute it */
2511         OPCTable[OPC] ();
2512
2513         /* Count cycles */
2514         TotalCycles += Cycles;
2515     }
2516 }
2517
2518
2519