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