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