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