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