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