]> git.sur5r.net Git - cc65/blob - src/sim65/cpucore.c
Working on the plugin interface
[cc65] / src / sim65 / cpucore.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                   cpucore.c                               */
4 /*                                                                           */
5 /*                        CPU core for the 6502 simulator                    */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2002      Ullrich von Bassewitz                                       */
10 /*               Wacholderweg 14                                             */
11 /*               D-70597 Stuttgart                                           */
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     PC += 3;
1028 }
1029
1030
1031
1032 static void OPC_6502_6D (void)
1033 /* Opcode $6D: ADC abs */
1034 {
1035     unsigned Addr;
1036     Cycles = 4;
1037     Addr   = MemReadWord (PC+1);
1038     ADC (MemReadByte (Addr));
1039     PC += 3;
1040 }
1041
1042
1043
1044 static void OPC_6502_6E (void)
1045 /* Opcode $6E: ROR abs */
1046 {
1047     unsigned Addr;
1048     unsigned Val;
1049     Cycles = 6;
1050     Addr = MemReadWord (PC+1);
1051     Val  = MemReadByte (Addr);
1052     ROR (Val);
1053     MemWriteByte (Addr, Val);
1054     PC += 3;
1055 }
1056
1057
1058
1059 static void OPC_6502_70 (void)
1060 /* Opcode $70: BVS */
1061 {
1062     BRANCH (GET_OF ());
1063 }
1064
1065
1066
1067 static void OPC_6502_71 (void)
1068 /* Opcode $71: ADC (zp),y */
1069 {
1070     unsigned char ZPAddr;
1071     unsigned Addr;
1072     Cycles = 5;
1073     ZPAddr = MemReadByte (PC+1);
1074     Addr   = MemReadZPWord (ZPAddr);
1075     if (PAGE_CROSS (Addr, YR)) {
1076         ++Cycles;
1077     }
1078     ADC (MemReadByte (Addr + YR));
1079     PC += 2;
1080 }
1081
1082
1083
1084 static void OPC_6502_75 (void)
1085 /* Opcode $75: ADC zp,x */
1086 {
1087     unsigned char ZPAddr;
1088     Cycles = 4;
1089     ZPAddr = MemReadByte (PC+1) + XR;
1090     ADC (MemReadByte (ZPAddr));
1091     PC += 2;
1092 }
1093
1094
1095
1096 static void OPC_6502_76 (void)
1097 /* Opcode $76: ROR zp,x */
1098 {
1099     unsigned char ZPAddr;
1100     unsigned Val;
1101     Cycles = 6;
1102     ZPAddr = MemReadByte (PC+1) + XR;
1103     Val    = MemReadByte (ZPAddr);
1104     ROR (Val);
1105     MemWriteByte (ZPAddr, Val);
1106     PC += 2;
1107 }
1108
1109
1110
1111 static void OPC_6502_78 (void)
1112 /* Opcode $78: SEI */
1113 {
1114     Cycles = 2;
1115     SET_IF (1);
1116     PC += 1;
1117 }
1118
1119
1120
1121 static void OPC_6502_79 (void)
1122 /* Opcode $79: ADC abs,y */
1123 {
1124     unsigned Addr;
1125     Cycles = 4;
1126     Addr   = MemReadWord (PC+1);
1127     if (PAGE_CROSS (Addr, YR)) {
1128         ++Cycles;
1129     }
1130     ADC (MemReadByte (Addr + YR));
1131     PC += 3;
1132 }
1133
1134
1135
1136 static void OPC_6502_7D (void)
1137 /* Opcode $7D: ADC abs,x */
1138 {
1139     unsigned Addr;
1140     Cycles = 4;
1141     Addr   = MemReadWord (PC+1);
1142     if (PAGE_CROSS (Addr, XR)) {
1143         ++Cycles;
1144     }
1145     ADC (MemReadByte (Addr + XR));
1146     PC += 3;
1147 }
1148
1149
1150
1151 static void OPC_6502_7E (void)
1152 /* Opcode $7E: ROR abs,x */
1153 {
1154     unsigned Addr;
1155     unsigned Val;
1156     Cycles = 7;
1157     Addr = MemReadByte (PC+1) + XR;
1158     Val  = MemReadByte (Addr);
1159     ROR (Val);
1160     MemWriteByte (Addr, Val);
1161     PC += 3;
1162 }
1163
1164
1165
1166 static void OPC_6502_81 (void)
1167 /* Opcode $81: STA (zp,x) */
1168 {
1169     unsigned char ZPAddr;
1170     unsigned Addr;
1171     Cycles = 6;
1172     ZPAddr = MemReadByte (PC+1) + XR;
1173     Addr   = MemReadZPWord (ZPAddr);
1174     MemWriteByte (Addr, AC);
1175     PC += 2;
1176 }
1177
1178
1179
1180 static void OPC_6502_84 (void)
1181 /* Opcode $84: STY zp */
1182 {
1183     unsigned char ZPAddr;
1184     Cycles = 3;
1185     ZPAddr = MemReadByte (PC+1);
1186     MemWriteByte (ZPAddr, YR);
1187     PC += 2;
1188 }
1189
1190
1191
1192 static void OPC_6502_85 (void)
1193 /* Opcode $85: STA zp */
1194 {
1195     unsigned char ZPAddr;
1196     Cycles = 3;
1197     ZPAddr = MemReadByte (PC+1);
1198     MemWriteByte (ZPAddr, AC);
1199     PC += 2;
1200 }
1201
1202
1203
1204 static void OPC_6502_86 (void)
1205 /* Opcode $86: STX zp */
1206 {
1207     unsigned char ZPAddr;
1208     Cycles = 3;
1209     ZPAddr = MemReadByte (PC+1);
1210     MemWriteByte (ZPAddr, XR);
1211     PC += 2;
1212 }
1213
1214
1215
1216 static void OPC_6502_88 (void)
1217 /* Opcode $88: DEY */
1218 {
1219     Cycles = 2;
1220     --YR;
1221     TEST_ZF (YR);
1222     TEST_SF (YR);
1223     PC += 1;
1224 }
1225
1226
1227
1228 static void OPC_6502_8A (void)
1229 /* Opcode $8A: TXA */
1230 {
1231     Cycles = 2;
1232     AC = XR;
1233     TEST_ZF (AC);
1234     TEST_SF (AC);
1235     PC += 1;
1236 }
1237
1238
1239
1240 static void OPC_6502_8C (void)
1241 /* Opcode $8C: STY abs */
1242 {
1243     unsigned Addr;
1244     Cycles = 4;
1245     Addr = MemReadWord (PC+1);
1246     MemWriteByte (Addr, YR);
1247     PC += 3;
1248 }
1249
1250
1251
1252 static void OPC_6502_8D (void)
1253 /* Opcode $8D: STA abs */
1254 {
1255     unsigned Addr;
1256     Cycles = 4;
1257     Addr = MemReadWord (PC+1);
1258     MemWriteByte (Addr, AC);
1259     PC += 3;
1260 }
1261
1262
1263
1264 static void OPC_6502_8E (void)
1265 /* Opcode $8E: STX abs */
1266 {
1267     unsigned Addr;
1268     Cycles = 4;
1269     Addr = MemReadWord (PC+1);
1270     MemWriteByte (Addr, XR);
1271     PC += 3;
1272 }
1273
1274
1275
1276 static void OPC_6502_90 (void)
1277 /* Opcode $90: BCC */
1278 {
1279     BRANCH (!GET_CF ());
1280 }
1281
1282
1283
1284 static void OPC_6502_91 (void)
1285 /* Opcode $91: sta (zp),y */
1286 {
1287     unsigned char ZPAddr;
1288     unsigned Addr;
1289     Cycles = 6;
1290     ZPAddr = MemReadByte (PC+1);
1291     Addr   = MemReadZPWord (ZPAddr) + YR;
1292     MemWriteByte (Addr, AC);
1293     PC += 2;
1294 }
1295
1296
1297
1298 static void OPC_6502_94 (void)
1299 /* Opcode $94: STY zp,x */
1300 {
1301     unsigned char ZPAddr;
1302     Cycles = 4;
1303     ZPAddr = MemReadByte (PC+1) + XR;
1304     MemWriteByte (ZPAddr, YR);
1305     PC += 2;
1306 }
1307
1308
1309
1310 static void OPC_6502_95 (void)
1311 /* Opcode $95: STA zp,x */
1312 {
1313     unsigned char ZPAddr;
1314     Cycles = 4;
1315     ZPAddr = MemReadByte (PC+1) + XR;
1316     MemWriteByte (ZPAddr, AC);
1317     PC += 2;
1318 }
1319
1320
1321
1322 static void OPC_6502_96 (void)
1323 /* Opcode $96: stx zp,y */
1324 {
1325     unsigned char ZPAddr;
1326     Cycles = 4;
1327     ZPAddr = MemReadByte (PC+1) + YR;
1328     MemWriteByte (ZPAddr, XR);
1329     PC += 2;
1330 }
1331
1332
1333
1334 static void OPC_6502_98 (void)
1335 /* Opcode $98: TYA */
1336 {
1337     Cycles = 2;
1338     AC = YR;
1339     TEST_ZF (AC);
1340     TEST_SF (AC);
1341     PC += 1;
1342 }
1343
1344
1345
1346 static void OPC_6502_99 (void)
1347 /* Opcode $99: STA abs,y */
1348 {
1349     unsigned Addr;
1350     Cycles = 5;
1351     Addr   = MemReadWord (PC+1) + YR;
1352     MemWriteByte (Addr, AC);
1353     PC += 3;
1354 }
1355
1356
1357
1358 static void OPC_6502_9A (void)
1359 /* Opcode $9A: TXS */
1360 {
1361     Cycles = 2;
1362     SP = XR;
1363     PC += 1;
1364 }
1365
1366
1367
1368 static void OPC_6502_9D (void)
1369 /* Opcode $9D: STA abs,x */
1370 {
1371     unsigned Addr;
1372     Cycles = 5;
1373     Addr   = MemReadWord (PC+1) + XR;
1374     MemWriteByte (Addr, AC);
1375     PC += 3;
1376 }
1377
1378
1379
1380 static void OPC_6502_A0 (void)
1381 /* Opcode $A0: LDY #imm */
1382 {
1383     Cycles = 2;
1384     YR = MemReadByte (PC+1);
1385     TEST_ZF (YR);
1386     TEST_SF (YR);
1387     PC += 2;
1388 }
1389
1390
1391
1392 static void OPC_6502_A1 (void)
1393 /* Opcode $A1: LDA (zp,x) */
1394 {
1395     unsigned char ZPAddr;
1396     unsigned Addr;
1397     Cycles = 6;
1398     ZPAddr = MemReadByte (PC+1) + XR;
1399     Addr = MemReadZPWord (ZPAddr);
1400     AC = MemReadByte (Addr);
1401     TEST_ZF (AC);
1402     TEST_SF (AC);
1403     PC += 2;
1404 }
1405
1406
1407
1408 static void OPC_6502_A2 (void)
1409 /* Opcode $A2: LDX #imm */
1410 {
1411     Cycles = 2;
1412     XR = MemReadByte (PC+1);
1413     TEST_ZF (XR);
1414     TEST_SF (XR);
1415     PC += 2;
1416 }
1417
1418
1419
1420 static void OPC_6502_A4 (void)
1421 /* Opcode $A4: LDY zp */
1422 {
1423     unsigned char ZPAddr;
1424     Cycles = 3;
1425     ZPAddr = MemReadByte (PC+1);
1426     YR = MemReadByte (ZPAddr);
1427     TEST_ZF (YR);
1428     TEST_SF (YR);
1429     PC += 2;
1430 }
1431
1432
1433
1434 static void OPC_6502_A5 (void)
1435 /* Opcode $A5: LDA zp */
1436 {
1437     unsigned char ZPAddr;
1438     Cycles = 3;
1439     ZPAddr = MemReadByte (PC+1);
1440     AC = MemReadByte (ZPAddr);
1441     TEST_ZF (AC);
1442     TEST_SF (AC);
1443     PC += 2;
1444 }
1445
1446
1447
1448 static void OPC_6502_A6 (void)
1449 /* Opcode $A6: LDX zp */
1450 {
1451     unsigned char ZPAddr;
1452     Cycles = 3;
1453     ZPAddr = MemReadByte (PC+1);
1454     XR = MemReadByte (ZPAddr);
1455     TEST_ZF (XR);
1456     TEST_SF (XR);
1457     PC += 2;
1458 }
1459
1460
1461
1462 static void OPC_6502_A8 (void)
1463 /* Opcode $A8: TAY */
1464 {
1465     Cycles = 2;
1466     YR = AC;
1467     TEST_ZF (YR);
1468     TEST_SF (YR);
1469     PC += 1;
1470 }
1471
1472
1473
1474 static void OPC_6502_A9 (void)
1475 /* Opcode $A9: LDA #imm */
1476 {
1477     Cycles = 2;
1478     AC = MemReadByte (PC+1);
1479     TEST_ZF (AC);
1480     TEST_SF (AC);
1481     PC += 2;
1482 }
1483
1484
1485
1486 static void OPC_6502_AA (void)
1487 /* Opcode $AA: TAX */
1488 {
1489     Cycles = 2;
1490     XR = AC;
1491     TEST_ZF (XR);
1492     TEST_SF (XR);
1493     PC += 1;
1494 }
1495
1496
1497
1498 static void OPC_6502_AC (void)
1499 /* Opcode $AC: LDY abs */
1500 {
1501     unsigned Addr;
1502     Cycles = 4;
1503     Addr   = MemReadWord (PC+1);
1504     YR     = MemReadByte (Addr);
1505     TEST_ZF (YR);
1506     TEST_SF (YR);
1507     PC += 3;
1508 }
1509
1510
1511
1512 static void OPC_6502_AD (void)
1513 /* Opcode $AD: LDA abs */
1514 {
1515     unsigned Addr;
1516     Cycles = 4;
1517     Addr   = MemReadWord (PC+1);
1518     AC     = MemReadByte (Addr);
1519     TEST_ZF (AC);
1520     TEST_SF (AC);
1521     PC += 3;
1522 }
1523
1524
1525
1526 static void OPC_6502_AE (void)
1527 /* Opcode $AE: LDX abs */
1528 {
1529     unsigned Addr;
1530     Cycles = 4;
1531     Addr   = MemReadWord (PC+1);
1532     XR     = MemReadByte (Addr);
1533     TEST_ZF (XR);
1534     TEST_SF (XR);
1535     PC += 3;
1536 }
1537
1538
1539
1540 static void OPC_6502_B0 (void)
1541 /* Opcode $B0: BCS */
1542 {
1543     BRANCH (GET_CF ());
1544 }
1545
1546
1547
1548 static void OPC_6502_B1 (void)
1549 /* Opcode $B1: LDA (zp),y */
1550 {
1551     unsigned char ZPAddr;
1552     unsigned Addr;
1553     Cycles = 5;
1554     ZPAddr = MemReadByte (PC+1);
1555     Addr   = MemReadZPWord (ZPAddr);
1556     if (PAGE_CROSS (Addr, YR)) {
1557         ++Cycles;
1558     }
1559     AC = MemReadByte (Addr + YR);
1560     TEST_ZF (AC);
1561     TEST_SF (AC);
1562     PC += 2;
1563 }
1564
1565
1566
1567 static void OPC_6502_B4 (void)
1568 /* Opcode $B4: LDY zp,x */
1569 {
1570     unsigned char ZPAddr;
1571     Cycles = 4;
1572     ZPAddr = MemReadByte (PC+1) + XR;
1573     YR     = MemReadByte (ZPAddr);
1574     TEST_ZF (YR);
1575     TEST_SF (YR);
1576     PC += 2;
1577 }
1578
1579
1580
1581 static void OPC_6502_B5 (void)
1582 /* Opcode $B5: LDA zp,x */
1583 {
1584     unsigned char ZPAddr;
1585     Cycles = 4;
1586     ZPAddr = MemReadByte (PC+1) + XR;
1587     AC     = MemReadByte (ZPAddr);
1588     TEST_ZF (AC);
1589     TEST_SF (AC);
1590     PC += 2;
1591 }
1592
1593
1594
1595 static void OPC_6502_B6 (void)
1596 /* Opcode $B6: LDX zp,y */
1597 {
1598     unsigned char ZPAddr;
1599     Cycles = 4;
1600     ZPAddr = MemReadByte (PC+1) + YR;
1601     XR     = MemReadByte (ZPAddr);
1602     TEST_ZF (XR);
1603     TEST_SF (XR);
1604     PC += 2;
1605 }
1606
1607
1608
1609 static void OPC_6502_B8 (void)
1610 /* Opcode $B8: CLV */
1611 {
1612     Cycles = 2;
1613     SET_OF (0);
1614     PC += 1;
1615 }
1616
1617
1618
1619 static void OPC_6502_B9 (void)
1620 /* Opcode $B9: LDA abs,y */
1621 {
1622     unsigned Addr;
1623     Cycles = 4;
1624     Addr = MemReadWord (PC+1);
1625     if (PAGE_CROSS (Addr, YR)) {
1626         ++Cycles;
1627     }
1628     AC = MemReadByte (Addr + YR);
1629     TEST_ZF (AC);
1630     TEST_SF (AC);
1631     PC += 3;
1632 }
1633
1634
1635
1636 static void OPC_6502_BA (void)
1637 /* Opcode $BA: TSX */
1638 {
1639     Cycles = 2;
1640     XR = SP;
1641     TEST_ZF (XR);
1642     TEST_SF (XR);
1643     PC += 1;
1644 }
1645
1646
1647
1648 static void OPC_6502_BC (void)
1649 /* Opcode $BC: LDY abs,x */
1650 {
1651     unsigned Addr;
1652     Cycles = 4;
1653     Addr = MemReadWord (PC+1);
1654     if (PAGE_CROSS (Addr, XR)) {
1655         ++Cycles;
1656     }
1657     YR = MemReadByte (Addr + XR);
1658     TEST_ZF (YR);
1659     TEST_SF (YR);
1660     PC += 3;
1661 }
1662
1663
1664
1665 static void OPC_6502_BD (void)
1666 /* Opcode $BD: LDA abs,x */
1667 {
1668     unsigned Addr;
1669     Cycles = 4;
1670     Addr = MemReadWord (PC+1);
1671     if (PAGE_CROSS (Addr, XR)) {
1672         ++Cycles;
1673     }
1674     AC = MemReadByte (Addr + XR);
1675     TEST_ZF (AC);
1676     TEST_SF (AC);
1677     PC += 3;
1678 }
1679
1680
1681
1682 static void OPC_6502_BE (void)
1683 /* Opcode $BE: LDX abs,y */
1684 {
1685     unsigned Addr;
1686     Cycles = 4;
1687     Addr = MemReadWord (PC+1);
1688     if (PAGE_CROSS (Addr, YR)) {
1689         ++Cycles;
1690     }
1691     XR = MemReadByte (Addr + YR);
1692     TEST_ZF (XR);
1693     TEST_SF (XR);
1694     PC += 3;
1695 }
1696
1697
1698
1699 static void OPC_6502_C0 (void)
1700 /* Opcode $C0: CPY #imm */
1701 {
1702     Cycles = 2;
1703     CMP (YR, MemReadByte (PC+1));
1704     PC += 2;
1705 }
1706
1707
1708
1709 static void OPC_6502_C1 (void)
1710 /* Opcode $C1: CMP (zp,x) */
1711 {
1712     unsigned char ZPAddr;
1713     unsigned Addr;
1714     Cycles = 6;
1715     ZPAddr = MemReadByte (PC+1) + XR;
1716     Addr   = MemReadZPWord (ZPAddr);
1717     CMP (AC, MemReadByte (Addr));
1718     PC += 2;
1719 }
1720
1721
1722
1723 static void OPC_6502_C4 (void)
1724 /* Opcode $C4: CPY zp */
1725 {
1726     unsigned char ZPAddr;
1727     Cycles = 3;
1728     ZPAddr = MemReadByte (PC+1);
1729     CMP (YR, MemReadByte (ZPAddr));
1730     PC += 2;
1731 }
1732
1733
1734
1735 static void OPC_6502_C5 (void)
1736 /* Opcode $C5: CMP zp */
1737 {
1738     unsigned char ZPAddr;
1739     Cycles = 3;
1740     ZPAddr = MemReadByte (PC+1);
1741     CMP (AC, MemReadByte (ZPAddr));
1742     PC += 2;
1743 }
1744
1745
1746
1747 static void OPC_6502_C6 (void)
1748 /* Opcode $C6: DEC zp */
1749 {
1750     unsigned char ZPAddr;
1751     unsigned char Val;
1752     Cycles = 5;
1753     ZPAddr = MemReadByte (PC+1);
1754     Val    = MemReadByte (ZPAddr) - 1;
1755     MemWriteByte (ZPAddr, Val);
1756     TEST_ZF (Val);
1757     TEST_SF (Val);
1758     PC += 2;
1759 }
1760
1761
1762
1763 static void OPC_6502_C8 (void)
1764 /* Opcode $C8: INY */
1765 {
1766     Cycles = 2;
1767     ++YR;
1768     TEST_ZF (YR);
1769     TEST_SF (YR);
1770     PC += 1;
1771 }
1772
1773
1774
1775 static void OPC_6502_C9 (void)
1776 /* Opcode $C9: CMP #imm */
1777 {
1778     Cycles = 2;
1779     CMP (AC, MemReadByte (PC+1));
1780     PC += 2;
1781 }
1782
1783
1784
1785 static void OPC_6502_CA (void)
1786 /* Opcode $CA: DEX */
1787 {
1788     Cycles = 2;
1789     --XR;
1790     TEST_ZF (XR);
1791     TEST_SF (XR);
1792     PC += 1;
1793 }
1794
1795
1796
1797 static void OPC_6502_CC (void)
1798 /* Opcode $CC: CPY abs */
1799 {
1800     unsigned Addr;
1801     Cycles = 4;
1802     Addr   = MemReadWord (PC+1);
1803     CMP (YR, MemReadByte (Addr));
1804     PC += 3;
1805 }
1806
1807
1808
1809 static void OPC_6502_CD (void)
1810 /* Opcode $CD: CMP abs */
1811 {
1812     unsigned Addr;
1813     Cycles = 4;
1814     Addr   = MemReadWord (PC+1);
1815     CMP (AC, MemReadByte (Addr));
1816     PC += 3;
1817 }
1818
1819
1820
1821 static void OPC_6502_CE (void)
1822 /* Opcode $CE: DEC abs */
1823 {
1824     unsigned Addr;
1825     unsigned char Val;
1826     Cycles = 6;
1827     Addr = MemReadWord (PC+1);
1828     Val  = MemReadByte (Addr) - 1;
1829     MemWriteByte (Addr, Val);
1830     TEST_ZF (Val);
1831     TEST_SF (Val);
1832     PC += 3;
1833 }
1834
1835
1836
1837 static void OPC_6502_D0 (void)
1838 /* Opcode $D0: BNE */
1839 {
1840     BRANCH (!GET_ZF ());
1841 }
1842
1843
1844
1845 static void OPC_6502_D1 (void)
1846 /* Opcode $D1: CMP (zp),y */
1847 {
1848     unsigned ZPAddr;
1849     unsigned Addr;
1850     Cycles = 5;
1851     ZPAddr = MemReadByte (PC+1);
1852     Addr   = MemReadWord (ZPAddr);
1853     if (PAGE_CROSS (Addr, YR)) {
1854         ++Cycles;
1855     }
1856     CMP (AC, MemReadByte (Addr + YR));
1857     PC += 2;
1858 }
1859
1860
1861
1862 static void OPC_6502_D5 (void)
1863 /* Opcode $D5: CMP zp,x */
1864 {
1865     unsigned char ZPAddr;
1866     Cycles = 4;
1867     ZPAddr = MemReadByte (PC+1) + XR;
1868     CMP (AC, MemReadByte (ZPAddr));
1869     PC += 2;
1870 }
1871
1872
1873
1874 static void OPC_6502_D6 (void)
1875 /* Opcode $D6: DEC zp,x */
1876 {
1877     unsigned char ZPAddr;
1878     unsigned char Val;
1879     Cycles = 6;
1880     ZPAddr = MemReadByte (PC+1) + XR;
1881     Val  = MemReadByte (ZPAddr) - 1;
1882     MemWriteByte (ZPAddr, Val);
1883     TEST_ZF (Val);
1884     TEST_SF (Val);
1885     PC += 2;
1886 }
1887
1888
1889
1890 static void OPC_6502_D8 (void)
1891 /* Opcode $D8: CLD */
1892 {
1893     Cycles = 2;
1894     SET_DF (0);
1895     PC += 1;
1896 }
1897
1898
1899
1900 static void OPC_6502_D9 (void)
1901 /* Opcode $D9: CMP abs,y */
1902 {
1903     unsigned Addr;
1904     Cycles = 4;
1905     Addr = MemReadWord (PC+1);
1906     if (PAGE_CROSS (Addr, YR)) {
1907         ++Cycles;
1908     }
1909     CMP (AC, MemReadByte (Addr + YR));
1910     PC += 3;
1911 }
1912
1913
1914
1915 static void OPC_6502_DD (void)
1916 /* Opcode $DD: CMP abs,x */
1917 {
1918     unsigned Addr;
1919     Cycles = 4;
1920     Addr = MemReadWord (PC+1);
1921     if (PAGE_CROSS (Addr, XR)) {
1922         ++Cycles;
1923     }
1924     CMP (AC, MemReadByte (Addr + XR));
1925     PC += 3;
1926 }
1927
1928
1929
1930 static void OPC_6502_DE (void)
1931 /* Opcode $DE: DEC abs,x */
1932 {
1933     unsigned Addr;
1934     unsigned char Val;
1935     Cycles = 7;
1936     Addr = MemReadWord (PC+1) + XR;
1937     Val  = MemReadByte (Addr) - 1;
1938     MemWriteByte (Addr, Val);
1939     TEST_ZF (Val);
1940     TEST_SF (Val);
1941     PC += 3;
1942 }
1943
1944
1945
1946 static void OPC_6502_E0 (void)
1947 /* Opcode $E0: CPX #imm */
1948 {
1949     Cycles = 2;
1950     CMP (XR, MemReadByte (PC+1));
1951     PC += 2;
1952 }
1953
1954
1955
1956 static void OPC_6502_E1 (void)
1957 /* Opcode $E1: SBC (zp,x) */
1958 {
1959     unsigned char ZPAddr;
1960     unsigned Addr;
1961     Cycles = 6;
1962     ZPAddr = MemReadByte (PC+1) + XR;
1963     Addr   = MemReadZPWord (ZPAddr);
1964     SBC (MemReadByte (Addr));
1965     PC += 2;
1966 }
1967
1968
1969
1970 static void OPC_6502_E4 (void)
1971 /* Opcode $E4: CPX zp */
1972 {
1973     unsigned char ZPAddr;
1974     Cycles = 3;
1975     ZPAddr = MemReadByte (PC+1);
1976     CMP (XR, MemReadByte (ZPAddr));
1977     PC += 2;
1978 }
1979
1980
1981
1982 static void OPC_6502_E5 (void)
1983 /* Opcode $E5: SBC zp */
1984 {
1985     unsigned char ZPAddr;
1986     Cycles = 3;
1987     ZPAddr = MemReadByte (PC+1);
1988     SBC (MemReadByte (ZPAddr));
1989     PC += 2;
1990 }
1991
1992
1993
1994 static void OPC_6502_E6 (void)
1995 /* Opcode $E6: INC zp */
1996 {
1997     unsigned char ZPAddr;
1998     unsigned char Val;
1999     Cycles = 5;
2000     ZPAddr = MemReadByte (PC+1);
2001     Val    = MemReadByte (ZPAddr) + 1;
2002     MemWriteByte (ZPAddr, Val);
2003     TEST_ZF (Val);
2004     TEST_SF (Val);
2005     PC += 2;
2006 }
2007
2008
2009
2010 static void OPC_6502_E8 (void)
2011 /* Opcode $E8: INX */
2012 {
2013     Cycles = 2;
2014     ++XR;
2015     TEST_ZF (XR);
2016     TEST_SF (XR);
2017     PC += 1;
2018 }
2019
2020
2021
2022 static void OPC_6502_E9 (void)
2023 /* Opcode $E9: SBC #imm */
2024 {
2025     Cycles = 2;
2026     SBC (MemReadByte (PC+1));
2027     PC += 2;
2028 }
2029
2030
2031
2032 static void OPC_6502_EA (void)
2033 /* Opcode $EA: NOP */
2034 {
2035     /* This one is easy... */
2036     Cycles = 2;
2037     PC += 1;
2038 }
2039
2040
2041
2042 static void OPC_6502_EC (void)
2043 /* Opcode $EC: CPX abs */
2044 {
2045     unsigned Addr;
2046     Cycles = 4;
2047     Addr   = MemReadWord (PC+1);
2048     CMP (XR, MemReadByte (Addr));
2049     PC += 3;
2050 }
2051
2052
2053
2054 static void OPC_6502_ED (void)
2055 /* Opcode $ED: SBC abs */
2056 {
2057     unsigned Addr;
2058     Cycles = 4;
2059     Addr   = MemReadWord (PC+1);
2060     SBC (MemReadByte (Addr));
2061     PC += 3;
2062 }
2063
2064
2065
2066 static void OPC_6502_EE (void)
2067 /* Opcode $EE: INC abs */
2068 {
2069     unsigned Addr;
2070     unsigned char Val;
2071     Cycles = 6;
2072     Addr = MemReadWord (PC+1);
2073     Val  = MemReadByte (Addr) + 1;
2074     MemWriteByte (Addr, Val);
2075     TEST_ZF (Val);
2076     TEST_SF (Val);
2077     PC += 3;
2078 }
2079
2080
2081
2082 static void OPC_6502_F0 (void)
2083 /* Opcode $F0: BEQ */
2084 {
2085     BRANCH (GET_ZF ());
2086 }
2087
2088
2089
2090 static void OPC_6502_F1 (void)
2091 /* Opcode $F1: SBC (zp),y */
2092 {
2093     unsigned char ZPAddr;
2094     unsigned Addr;
2095     Cycles = 5;
2096     ZPAddr = MemReadByte (PC+1);
2097     Addr   = MemReadZPWord (ZPAddr);
2098     if (PAGE_CROSS (Addr, YR)) {
2099         ++Cycles;
2100     }
2101     SBC (MemReadByte (Addr + YR));
2102     PC += 2;
2103 }
2104
2105
2106
2107 static void OPC_6502_F5 (void)
2108 /* Opcode $F5: SBC zp,x */
2109 {
2110     unsigned char ZPAddr;
2111     Cycles = 4;
2112     ZPAddr = MemReadByte (PC+1) + XR;
2113     SBC (MemReadByte (ZPAddr));
2114     PC += 2;
2115 }
2116
2117
2118
2119 static void OPC_6502_F6 (void)
2120 /* Opcode $F6: INC zp,x */
2121 {
2122     unsigned char ZPAddr;
2123     unsigned char Val;
2124     Cycles = 6;
2125     ZPAddr = MemReadByte (PC+1) + XR;
2126     Val  = MemReadByte (ZPAddr) + 1;
2127     MemWriteByte (ZPAddr, Val);
2128     TEST_ZF (Val);
2129     TEST_SF (Val);
2130     PC += 2;
2131 }
2132
2133
2134
2135 static void OPC_6502_F8 (void)
2136 /* Opcode $F8: SED */
2137 {
2138     SET_DF (1);
2139 }
2140
2141
2142
2143 static void OPC_6502_F9 (void)
2144 /* Opcode $F9: SBC abs,y */
2145 {
2146     unsigned Addr;
2147     Cycles = 4;
2148     Addr   = MemReadWord (PC+1);
2149     if (PAGE_CROSS (Addr, YR)) {
2150         ++Cycles;
2151     }
2152     SBC (MemReadByte (Addr + YR));
2153     PC += 3;
2154 }
2155
2156
2157
2158 static void OPC_6502_FD (void)
2159 /* Opcode $FD: SBC abs,x */
2160 {
2161     unsigned Addr;
2162     Cycles = 4;
2163     Addr   = MemReadWord (PC+1);
2164     if (PAGE_CROSS (Addr, XR)) {
2165         ++Cycles;
2166     }
2167     SBC (MemReadByte (Addr + XR));
2168     PC += 3;
2169 }
2170
2171
2172
2173 static void OPC_6502_FE (void)
2174 /* Opcode $FE: INC abs,x */
2175 {
2176     unsigned Addr;
2177     unsigned char Val;
2178     Cycles = 7;
2179     Addr = MemReadWord (PC+1) + XR;
2180     Val  = MemReadByte (Addr) + 1;
2181     MemWriteByte (Addr, Val);
2182     TEST_ZF (Val);
2183     TEST_SF (Val);
2184     PC += 3;
2185 }
2186
2187
2188
2189 /*****************************************************************************/
2190 /*                                   Data                                    */
2191 /*****************************************************************************/
2192
2193
2194
2195 /* Opcode handler table */
2196 typedef void (*OPCFunc) (void);
2197 static OPCFunc OPCTable[256] = {
2198     OPC_6502_00,
2199     OPC_6502_01,
2200     OPC_Illegal,
2201     OPC_Illegal,
2202     OPC_Illegal,
2203     OPC_6502_05,
2204     OPC_6502_06,
2205     OPC_Illegal,
2206     OPC_6502_08,
2207     OPC_6502_09,
2208     OPC_6502_0A,
2209     OPC_Illegal,
2210     OPC_Illegal,
2211     OPC_6502_0D,
2212     OPC_6502_0E,
2213     OPC_Illegal,
2214     OPC_6502_10,
2215     OPC_6502_11,
2216     OPC_Illegal,
2217     OPC_Illegal,
2218     OPC_Illegal,
2219     OPC_6502_15,
2220     OPC_6502_16,
2221     OPC_Illegal,
2222     OPC_6502_18,
2223     OPC_6502_19,
2224     OPC_Illegal,
2225     OPC_Illegal,
2226     OPC_Illegal,
2227     OPC_6502_1D,
2228     OPC_6502_1E,
2229     OPC_Illegal,
2230     OPC_6502_20,
2231     OPC_6502_21,
2232     OPC_Illegal,
2233     OPC_Illegal,
2234     OPC_6502_24,
2235     OPC_6502_25,
2236     OPC_6502_26,
2237     OPC_Illegal,
2238     OPC_6502_28,
2239     OPC_6502_29,
2240     OPC_6502_2A,
2241     OPC_Illegal,
2242     OPC_6502_2C,
2243     OPC_6502_2D,
2244     OPC_6502_2E,
2245     OPC_Illegal,
2246     OPC_6502_30,
2247     OPC_6502_31,
2248     OPC_Illegal,
2249     OPC_Illegal,
2250     OPC_Illegal,
2251     OPC_6502_35,
2252     OPC_6502_36,
2253     OPC_Illegal,
2254     OPC_6502_38,
2255     OPC_6502_39,
2256     OPC_Illegal,
2257     OPC_Illegal,
2258     OPC_Illegal,
2259     OPC_6502_3D,
2260     OPC_6502_3E,
2261     OPC_Illegal,
2262     OPC_6502_40,
2263     OPC_6502_41,
2264     OPC_Illegal,
2265     OPC_Illegal,
2266     OPC_Illegal,
2267     OPC_6502_45,
2268     OPC_6502_46,
2269     OPC_Illegal,
2270     OPC_6502_48,
2271     OPC_6502_49,
2272     OPC_6502_4A,
2273     OPC_Illegal,
2274     OPC_6502_4C,
2275     OPC_6502_4D,
2276     OPC_6502_4E,
2277     OPC_Illegal,
2278     OPC_6502_50,
2279     OPC_6502_51,
2280     OPC_Illegal,
2281     OPC_Illegal,
2282     OPC_Illegal,
2283     OPC_6502_55,
2284     OPC_6502_56,
2285     OPC_Illegal,
2286     OPC_6502_58,
2287     OPC_6502_59,
2288     OPC_Illegal,
2289     OPC_Illegal,
2290     OPC_Illegal,
2291     OPC_6502_5D,
2292     OPC_6502_5E,
2293     OPC_Illegal,
2294     OPC_6502_60,
2295     OPC_6502_61,
2296     OPC_Illegal,
2297     OPC_Illegal,
2298     OPC_Illegal,
2299     OPC_6502_65,
2300     OPC_6502_66,
2301     OPC_Illegal,
2302     OPC_6502_68,
2303     OPC_6502_69,
2304     OPC_6502_6A,
2305     OPC_Illegal,
2306     OPC_6502_6C,
2307     OPC_6502_6D,
2308     OPC_6502_6E,
2309     OPC_Illegal,
2310     OPC_6502_70,
2311     OPC_6502_71,
2312     OPC_Illegal,
2313     OPC_Illegal,
2314     OPC_Illegal,
2315     OPC_6502_75,
2316     OPC_6502_76,
2317     OPC_Illegal,
2318     OPC_6502_78,
2319     OPC_6502_79,
2320     OPC_Illegal,
2321     OPC_Illegal,
2322     OPC_Illegal,
2323     OPC_6502_7D,
2324     OPC_6502_7E,
2325     OPC_Illegal,
2326     OPC_Illegal,
2327     OPC_6502_81,
2328     OPC_Illegal,
2329     OPC_Illegal,
2330     OPC_6502_84,
2331     OPC_6502_85,
2332     OPC_6502_86,
2333     OPC_Illegal,
2334     OPC_6502_88,
2335     OPC_Illegal,
2336     OPC_6502_8A,
2337     OPC_Illegal,
2338     OPC_6502_8C,
2339     OPC_6502_8D,
2340     OPC_6502_8E,
2341     OPC_Illegal,
2342     OPC_6502_90,
2343     OPC_6502_91,
2344     OPC_Illegal,
2345     OPC_Illegal,
2346     OPC_6502_94,
2347     OPC_6502_95,
2348     OPC_6502_96,
2349     OPC_Illegal,
2350     OPC_6502_98,
2351     OPC_6502_99,
2352     OPC_6502_9A,
2353     OPC_Illegal,
2354     OPC_Illegal,
2355     OPC_6502_9D,
2356     OPC_Illegal,
2357     OPC_Illegal,
2358     OPC_6502_A0,
2359     OPC_6502_A1,
2360     OPC_6502_A2,
2361     OPC_Illegal,
2362     OPC_6502_A4,
2363     OPC_6502_A5,
2364     OPC_6502_A6,
2365     OPC_Illegal,
2366     OPC_6502_A8,
2367     OPC_6502_A9,
2368     OPC_6502_AA,
2369     OPC_Illegal,
2370     OPC_6502_AC,
2371     OPC_6502_AD,
2372     OPC_6502_AE,
2373     OPC_Illegal,
2374     OPC_6502_B0,
2375     OPC_6502_B1,
2376     OPC_Illegal,
2377     OPC_Illegal,
2378     OPC_6502_B4,
2379     OPC_6502_B5,
2380     OPC_6502_B6,
2381     OPC_Illegal,
2382     OPC_6502_B8,
2383     OPC_6502_B9,
2384     OPC_6502_BA,
2385     OPC_Illegal,
2386     OPC_6502_BC,
2387     OPC_6502_BD,
2388     OPC_6502_BE,
2389     OPC_Illegal,
2390     OPC_6502_C0,
2391     OPC_6502_C1,
2392     OPC_Illegal,
2393     OPC_Illegal,
2394     OPC_6502_C4,
2395     OPC_6502_C5,
2396     OPC_6502_C6,
2397     OPC_Illegal,
2398     OPC_6502_C8,
2399     OPC_6502_C9,
2400     OPC_6502_CA,
2401     OPC_Illegal,
2402     OPC_6502_CC,
2403     OPC_6502_CD,
2404     OPC_6502_CE,
2405     OPC_Illegal,
2406     OPC_6502_D0,
2407     OPC_6502_D1,
2408     OPC_Illegal,
2409     OPC_Illegal,
2410     OPC_Illegal,
2411     OPC_6502_D5,
2412     OPC_6502_D6,
2413     OPC_Illegal,
2414     OPC_6502_D8,
2415     OPC_6502_D9,
2416     OPC_Illegal,
2417     OPC_Illegal,
2418     OPC_Illegal,
2419     OPC_6502_DD,
2420     OPC_6502_DE,
2421     OPC_Illegal,
2422     OPC_6502_E0,
2423     OPC_6502_E1,
2424     OPC_Illegal,
2425     OPC_Illegal,
2426     OPC_6502_E4,
2427     OPC_6502_E5,
2428     OPC_6502_E6,
2429     OPC_Illegal,
2430     OPC_6502_E8,
2431     OPC_6502_E9,
2432     OPC_6502_EA,
2433     OPC_Illegal,
2434     OPC_6502_EC,
2435     OPC_6502_ED,
2436     OPC_6502_EE,
2437     OPC_Illegal,
2438     OPC_6502_F0,
2439     OPC_6502_F1,
2440     OPC_Illegal,
2441     OPC_Illegal,
2442     OPC_Illegal,
2443     OPC_6502_F5,
2444     OPC_6502_F6,
2445     OPC_Illegal,
2446     OPC_6502_F8,
2447     OPC_6502_F9,
2448     OPC_Illegal,
2449     OPC_Illegal,
2450     OPC_Illegal,
2451     OPC_6502_FD,
2452     OPC_6502_FE,
2453     OPC_Illegal,
2454 };
2455
2456
2457
2458 /*****************************************************************************/
2459 /*                                   Code                                    */
2460 /*****************************************************************************/
2461
2462
2463
2464 void CPUInit (void)
2465 /* Initialize the CPU */
2466 {
2467     PC = MemReadWord (0xFFFC);
2468 }
2469
2470
2471
2472 void Reset (void)
2473 /* Reset the CPU */
2474 {
2475 }
2476
2477
2478
2479 void IRQ (void)
2480 /* Generate an IRQ */
2481 {
2482 }
2483
2484
2485
2486 void NMI (void)
2487 /* Generate an NMI */
2488 {
2489 }
2490
2491
2492
2493 void CPURun (void)
2494 /* Run the CPU */
2495 {
2496     while (!CPUHalted) {
2497
2498         /* Get the next opcode */
2499         unsigned char OPC = MemReadByte (PC);
2500
2501         printf ("%6lu %04X %02X A=%02X X=%02X Y=%02X %c%c%c%c%c%c%c\n",
2502                 TotalCycles, PC, OPC, AC, XR, YR,
2503                 GET_SF()? 'S' : '-',
2504                 GET_ZF()? 'Z' : '-',
2505                 GET_CF()? 'C' : '-',
2506                 GET_IF()? 'I' : '-',
2507                 GET_BF()? 'B' : '-',
2508                 GET_DF()? 'D' : '-',
2509                 GET_OF()? 'V' : '-');
2510
2511         /* Execute it */
2512         OPCTable[OPC] ();
2513
2514         /* Count cycles */
2515         TotalCycles += Cycles;
2516     }
2517 }
2518
2519
2520