2 * acpu.c - another 6502 CPU emulator
4 * Copyright (C) 2007-2010 Piotr Fusik
6 * This file is part of ASAP (Another Slight Atari Player),
7 * see http://asap.sourceforge.net
9 * ASAP is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2 of the License,
12 * or (at your option) any later version.
14 * ASAP is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty
16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 * See the GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with ASAP; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 /* How 6502 registers are stored in this emulator:
25 All variables are int, because modern processors (and Java bytecode)
26 tend to operate more effectively on these type than narrower ones.
27 pc is really an unsigned 16-bit integer.
28 a, x, y and s are unsigned 8-bit integers.
29 Flags are decomposed into three variables for improved performance.
31 nz contains 6502 flags N and Z.
32 N is set if (nz >= 0x80). Z is set if ((nz & 0xff) == 0).
33 Usually nz is simply assigned the unsigned 8-bit operation result.
34 There are just a few operations (ADC in decimal mode, BIT, PLP and RTI)
35 where both N and Z may be set. In these cases, N is reflected by the 8th
37 vdi contains rarely used flags V, D and I, as a combination
38 of V_FLAG, D_FLAG and I_FLAG. Other vdi bits are clear.
40 "Unofficial" opcodes are not documented as "legal" 6502 opcodes.
41 Their operation has been reverse-engineered on Atari 800XL and Atari 65XE.
42 Unofficial opcodes are identical to C64's 6510, except for 0x8b and 0xab.
43 The operation of "unstable" opcodes is partially uncertain.
44 Explanation is welcome.
46 Emulation of POKEY timer interrupts is included.
48 Two preprocessor symbols may be used to strip the size of this emulator.
49 Define ACPU_NO_DECIMAL to disable emulation of the BCD mode.
50 Define ACPU_NO_UNOFFICIAL to disable emulation of unofficial opcodes. */
52 #include "asap_internal.h"
54 CONST_ARRAY(int, opcode_cycles
)
55 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
56 7, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 4, 4, 6, 6, /* 0x */
57 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, /* 1x */
58 6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 4, 4, 6, 6, /* 2x */
59 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, /* 3x */
60 6, 6, 2, 8, 3, 3, 5, 5, 3, 2, 2, 2, 3, 4, 6, 6, /* 4x */
61 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, /* 5x */
62 6, 6, 2, 8, 3, 3, 5, 5, 4, 2, 2, 2, 5, 4, 6, 6, /* 6x */
63 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, /* 7x */
64 2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4, /* 8x */
65 2, 6, 2, 6, 4, 4, 4, 4, 2, 5, 2, 5, 5, 5, 5, 5, /* 9x */
66 2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 2, 4, 4, 4, 4, /* Ax */
67 2, 5, 2, 5, 4, 4, 4, 4, 2, 4, 2, 4, 4, 4, 4, 4, /* Bx */
68 2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6, /* Cx */
69 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, /* Dx */
70 2, 6, 2, 8, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 6, /* Ex */
71 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7 /* Fx */
74 #ifdef ACPU_NO_DECIMAL
79 V(int, tmp) = a + data + c; \
80 vdi = (vdi & (D_FLAG | I_FLAG)) + (((~(data ^ a) & (a ^ tmp)) >> 1) & V_FLAG); \
82 nz = a = tmp & 0xff; \
88 V(int, tmp) = a - data - 1 + c; \
89 vdi = (vdi & (D_FLAG | I_FLAG)) + ((((data ^ a) & (a ^ tmp)) >> 1) & V_FLAG); \
90 c = (tmp >= 0) ? 1 : 0; \
91 nz = a = tmp & 0xff; \
94 #else /* ACPU_NO_DECIMAL */
98 V(int, tmp) = a + data + c; \
100 if ((vdi & D_FLAG) == 0) { \
102 vdi = (vdi & (D_FLAG | I_FLAG)) + (((~(data ^ a) & (a ^ tmp)) >> 1) & V_FLAG); \
108 V(int, al) = (a & 0x0f) + (data & 0x0f) + c; \
110 tmp += (al < 26) ? 6 : -10; \
111 nz = ((tmp & 0x80) << 1) + (nz != 0 ? 1 : 0); \
112 vdi = (vdi & (D_FLAG | I_FLAG)) + (((~(data ^ a) & (a ^ tmp)) >> 1) & V_FLAG); \
115 a = (tmp + 0x60) & 0xff; \
126 V(int, tmp) = a - data - 1 + c; \
127 V(int, al) = (a & 0x0f) - (data & 0x0f) - 1 + c; \
128 vdi = (vdi & (D_FLAG | I_FLAG)) + ((((data ^ a) & (a ^ tmp)) >> 1) & V_FLAG); \
129 c = (tmp >= 0) ? 1 : 0; \
130 nz = a = tmp & 0xff; \
131 if ((vdi & D_FLAG) != 0) { \
134 a += (al < -10) ? 10 : -6; \
136 a = (a - 0x60) & 0xff; \
140 #endif /* ACPU_NO_DECIMAL */
142 #define zGetByte(addr) dGetByte((addr) & 0xff)
144 #define PEEK dGetByte(pc)
145 #define FETCH dGetByte(pc++)
147 #define ABSOLUTE addr = FETCH; addr += FETCH << 8
148 #define ABSOLUTE_X addr = FETCH; addr = (addr + (FETCH << 8) + x) & 0xffff
149 #define ABSOLUTE_Y addr = FETCH; addr = (addr + (FETCH << 8) + y) & 0xffff
150 #define ZPAGE addr = FETCH
151 #define ZPAGE_X addr = (FETCH + x) & 0xff
152 #define ZPAGE_Y addr = (FETCH + y) & 0xff
153 #define INDIRECT_X addr = (FETCH + x) & 0xff; addr = dGetByte(addr) + (zGetByte(addr + 1) << 8)
154 #define INDIRECT_Y addr = FETCH; addr = (dGetByte(addr) + (zGetByte(addr + 1) << 8) + y) & 0xffff
155 #define NCYCLES_X if ((addr & 0xff) < x) ast _ cycle++
156 #define NCYCLES_Y if ((addr & 0xff) < y) ast _ cycle++
158 #define PL(dest) s = (s + 1) & 0xff; dest = dGetByte(0x0100 + s)
159 #define PLP PL(vdi); nz = ((vdi & 0x80) << 1) + (~vdi & Z_FLAG); c = vdi & 1; vdi &= V_FLAG | D_FLAG | I_FLAG
160 #define PH(data) dPutByte(0x0100 + s, data); s = (s - 1) & 0xff
161 #define PHW(data) PH((data) >> 8); PH(TO_BYTE(data))
162 #define PHP(bflag) PH(((nz | (nz >> 1)) & 0x80) + vdi + ((nz & 0xff) == 0 ? Z_FLAG : 0) + c + bflag)
163 #define PHPB0 PHP(0x20) /* push flags with B flag clear (NMI, IRQ) */
164 #define PHPB1 PHP(0x30) /* push flags with B flag set (PHP, BRK) */
167 #define LDA nz = a = GetByte(addr)
168 #define LDA_ZP nz = a = dGetByte(addr)
169 #define LDX nz = x = GetByte(addr)
170 #define LDX_ZP nz = x = dGetByte(addr)
171 #define LDY nz = y = GetByte(addr)
172 #define LDY_ZP nz = y = dGetByte(addr)
173 #define LAX nz = x = a = GetByte(addr)
174 #define LAX_ZP nz = x = a = dGetByte(addr)
175 #define STA PutByte(addr, a)
176 #define STA_ZP dPutByte(addr, a)
177 #define STX PutByte(addr, x)
178 #define STX_ZP dPutByte(addr, x)
179 #define STY PutByte(addr, y)
180 #define STY_ZP dPutByte(addr, y)
181 #define SAX data = a & x; PutByte(addr, data)
182 #define SAX_ZP data = a & x; dPutByte(addr, data)
183 #define CMP nz = GetByte(addr); c = (a >= nz) ? 1 : 0; nz = (a - nz) & 0xff
184 #define CMP_ZP nz = dGetByte(addr); c = (a >= nz) ? 1 : 0; nz = (a - nz) & 0xff
185 #define CPX nz = GetByte(addr); c = (x >= nz) ? 1 : 0; nz = (x - nz) & 0xff
186 #define CPX_ZP nz = dGetByte(addr); c = (x >= nz) ? 1 : 0; nz = (x - nz) & 0xff
187 #define CPY nz = GetByte(addr); c = (y >= nz) ? 1 : 0; nz = (y - nz) & 0xff
188 #define CPY_ZP nz = dGetByte(addr); c = (y >= nz) ? 1 : 0; nz = (y - nz) & 0xff
189 #define AND nz = a &= GetByte(addr)
190 #define AND_ZP nz = a &= dGetByte(addr)
191 #define ORA nz = a |= GetByte(addr)
192 #define ORA_ZP nz = a |= dGetByte(addr)
193 #define EOR nz = a ^= GetByte(addr)
194 #define EOR_ZP nz = a ^= dGetByte(addr)
195 #define ADC data = GetByte(addr); DO_ADC
196 #define ADC_ZP data = dGetByte(addr); DO_ADC
197 #define SBC data = GetByte(addr); DO_SBC
198 #define SBC_ZP data = dGetByte(addr); DO_SBC
200 #define ASL RMW_GetByte(nz, addr); c = nz >> 7; nz = (nz << 1) & 0xff; PutByte(addr, nz)
201 #define ASL_ZP nz = dGetByte(addr); c = nz >> 7; nz = (nz << 1) & 0xff; dPutByte(addr, nz)
202 #define ROL RMW_GetByte(nz, addr); nz = (nz << 1) + c; c = nz >> 8; nz &= 0xff; PutByte(addr, nz)
203 #define ROL_ZP nz = dGetByte(addr); nz = (nz << 1) + c; c = nz >> 8; nz &= 0xff; dPutByte(addr, nz)
204 #define LSR RMW_GetByte(nz, addr); c = nz & 1; nz >>= 1; PutByte(addr, nz)
205 #define LSR_ZP nz = dGetByte(addr); c = nz & 1; nz >>= 1; dPutByte(addr, nz)
206 #define ROR RMW_GetByte(nz, addr); nz += c << 8; c = nz & 1; nz >>= 1; PutByte(addr, nz)
207 #define ROR_ZP nz = dGetByte(addr) + (c << 8); c = nz & 1; nz >>= 1; dPutByte(addr, nz)
208 #define DEC RMW_GetByte(nz, addr); nz = (nz - 1) & 0xff; PutByte(addr, nz)
209 #define DEC_ZP nz = dGetByte(addr); nz = (nz - 1) & 0xff; dPutByte(addr, nz)
210 #define INC RMW_GetByte(nz, addr); nz = (nz + 1) & 0xff; PutByte(addr, nz)
211 #define INC_ZP nz = dGetByte(addr); nz = (nz + 1) & 0xff; dPutByte(addr, nz)
213 #define ASO ASL; nz = a |= nz
214 #define ASO_ZP ASL_ZP; nz = a |= nz
215 #define RLA ROL; nz = a &= nz
216 #define RLA_ZP ROL_ZP; nz = a &= nz
217 #define LSE LSR; nz = a ^= nz
218 #define LSE_ZP LSR_ZP; nz = a ^= nz
219 #define RRA ROR; data = nz; DO_ADC
220 #define RRA_ZP ROR_ZP; data = nz; DO_ADC
221 #define DCM DEC; c = (a >= nz) ? 1 : 0; nz = (a - nz) & 0xff
222 #define DCM_ZP DEC_ZP; c = (a >= nz) ? 1 : 0; nz = (a - nz) & 0xff
223 #define INS INC; data = nz; DO_SBC
224 #define INS_ZP INC_ZP; data = nz; DO_SBC
226 #define BRANCH(cond) \
228 addr = SBYTE(PEEK); \
231 if ((addr ^ pc) >> 8 != 0) \
241 if ((vdi & I_FLAG) == 0 && ast _ irqst != 0xff) { \
245 pc = dGetWord(0xfffe); \
249 /* Runs 6502 emulation for the specified number of Atari scanlines.
250 Each scanline is 114 cycles of which 9 is taken by ANTIC for memory refresh. */
251 FUNC(void, Cpu_RunScanlines
, (P(ASAP_State PTR
, ast
), P(int, scanlines
)))
253 /* copy registers from ASAP_State to local variables for improved performance */
262 V(int, next_event_cycle
);
272 ast _ next_scanline_cycle
= 114;
273 next_event_cycle
= 114;
274 cycle_limit
= 114 * scanlines
;
275 if (next_event_cycle
> ast _ timer1_cycle
)
276 next_event_cycle
= ast _ timer1_cycle
;
277 if (next_event_cycle
> ast _ timer2_cycle
)
278 next_event_cycle
= ast _ timer2_cycle
;
279 if (next_event_cycle
> ast _ timer4_cycle
)
280 next_event_cycle
= ast _ timer4_cycle
;
281 ast _ nearest_event_cycle
= next_event_cycle
;
287 if (cycle
>= ast _ nearest_event_cycle
) {
288 if (cycle
>= ast _ next_scanline_cycle
) {
289 if (++ast _ scanline_number
== (ast _ module_info
.ntsc
? 262 : 312))
290 ast _ scanline_number
= 0;
291 ast _ cycle
= cycle
+= 9;
292 ast _ next_scanline_cycle
+= 114;
293 if (--scanlines
<= 0)
296 next_event_cycle
= ast _ next_scanline_cycle
;
297 #define CHECK_TIMER_IRQ(ch) \
298 if (cycle >= ast _ timer##ch##_cycle) { \
299 ast _ irqst &= ~ch; \
300 ast _ timer##ch##_cycle = NEVER; \
302 else if (next_event_cycle > ast _ timer##ch##_cycle) \
303 next_event_cycle = ast _ timer##ch##_cycle;
307 ast _ nearest_event_cycle
= next_event_cycle
;
312 trace_cpu(ast
, pc
, a
, x
, y
, s
, nz
, vdi
, c
);
315 ast _ cycle
+= opcode_cycles
[data
];
322 pc
= dGetWord(0xfffe);
324 case 0x01: /* ORA (ab,x) */
328 case 0x02: /* CIM [unofficial] */
340 ast _ scanline_number
= (ast _ scanline_number
+ scanlines
- 1) % (ast _ module_info
.ntsc
? 262 : 312);
342 ast _ cycle
= cycle_limit
;
344 #ifndef ACPU_NO_UNOFFICIAL
345 case 0x03: /* ASO (ab,x) [unofficial] */
349 case 0x04: /* NOP ab [unofficial] */
352 case 0x14: /* NOP ab,x [unofficial] */
358 case 0x80: /* NOP #ab [unofficial] */
365 case 0x07: /* ASO ab [unofficial] */
369 case 0x0b: /* ANC #ab [unofficial] */
374 case 0x0c: /* NOP abcd [unofficial] */
377 case 0x0f: /* ASO abcd [unofficial] */
381 case 0x13: /* ASO (ab),y [unofficial] */
385 case 0x17: /* ASO ab,x [unofficial] */
389 case 0x1b: /* ASO abcd,y [unofficial] */
393 case 0x1c: /* NOP abcd,x [unofficial] */
399 if (FETCH
+ x
>= 0x100)
403 case 0x1f: /* ASO abcd,x [unofficial] */
407 case 0x23: /* RLA (ab,x) [unofficial] */
411 case 0x27: /* RLA ab [unofficial] */
415 case 0x2f: /* RLA abcd [unofficial] */
419 case 0x33: /* RLA (ab),y [unofficial] */
423 case 0x37: /* RLA ab,x [unofficial] */
427 case 0x3b: /* RLA abcd,y [unofficial] */
431 case 0x3f: /* RLA abcd,x [unofficial] */
435 case 0x43: /* LSE (ab,x) [unofficial] */
439 case 0x47: /* LSE ab [unofficial] */
443 case 0x4b: /* ALR #ab [unofficial] */
448 case 0x4f: /* LSE abcd [unofficial] */
452 case 0x53: /* LSE (ab),y [unofficial] */
456 case 0x57: /* LSE ab,x [unofficial] */
460 case 0x5b: /* LSE abcd,y [unofficial] */
464 case 0x5f: /* LSE abcd,x [unofficial] */
468 case 0x63: /* RRA (ab,x) [unofficial] */
472 case 0x67: /* RRA ab [unofficial] */
476 case 0x6b: /* ARR #ab [unofficial] */
478 nz
= a
= (data
>> 1) + (c
<< 7);
479 vdi
= (vdi
& (D_FLAG
| I_FLAG
)) + ((a
^ data
) & V_FLAG
);
480 #ifdef ACPU_NO_DECIMAL
483 if ((vdi
& D_FLAG
) == 0)
486 if ((data
& 0xf) >= 5)
487 a
= (a
& 0xf0) + ((a
+ 6) & 0xf);
489 a
= (a
+ 0x60) & 0xff;
497 case 0x6f: /* RRA abcd [unofficial] */
501 case 0x73: /* RRA (ab),y [unofficial] */
505 case 0x77: /* RRA ab,x [unofficial] */
509 case 0x7b: /* RRA abcd,y [unofficial] */
513 case 0x7f: /* RRA abcd,x [unofficial] */
517 case 0x83: /* SAX (ab,x) [unofficial] */
521 case 0x87: /* SAX ab [unofficial] */
525 case 0x8b: /* ANE #ab [unofficial] */
531 case 0x8f: /* SAX abcd [unofficial] */
535 case 0x93: /* SHA (ab),y [unofficial, unstable] */
537 data
= zGetByte(addr
+ 1);
538 addr
= (dGetByte(addr
) + (data
<< 8) + y
) & 0xffff;
539 data
= a
& x
& (data
+ 1);
542 case 0x97: /* SAX ab,y [unofficial] */
546 case 0x9b: /* SHS abcd,y [unofficial, unstable] */
547 /* S seems to be stable, only memory values vary */
550 addr
= (addr
+ (data
<< 8) + y
) & 0xffff;
552 data
= s
& (data
+ 1);
555 case 0x9c: /* SHY abcd,x [unofficial] */
558 addr
= (addr
+ (data
<< 8) + x
) & 0xffff;
559 data
= y
& (data
+ 1);
562 case 0x9e: /* SHX abcd,y [unofficial] */
565 addr
= (addr
+ (data
<< 8) + y
) & 0xffff;
566 data
= x
& (data
+ 1);
569 case 0x9f: /* SHA abcd,y [unofficial, unstable] */
572 addr
= (addr
+ (data
<< 8) + y
) & 0xffff;
573 data
= a
& x
& (data
+ 1);
576 case 0xa3: /* LAX (ab,x) [unofficial] */
580 case 0xa7: /* LAX ab [unofficial] */
584 case 0xab: /* ANX #ab [unofficial] */
587 case 0xaf: /* LAX abcd [unofficial] */
591 case 0xb3: /* LAX (ab),y [unofficial] */
596 case 0xb7: /* LAX ab,y [unofficial] */
600 case 0xbb: /* LAS abcd,y [unofficial] */
603 nz
= x
= a
= s
&= GetByte(addr
);
605 case 0xbf: /* LAX abcd,y [unofficial] */
610 case 0xc3: /* DCM (ab,x) [unofficial] */
614 case 0xc7: /* DCM ab [unofficial] */
618 case 0xcb: /* SBX #ab [unofficial] */
621 c
= (x
>= nz
) ? 1 : 0;
622 nz
= x
= (x
- nz
) & 0xff;
624 case 0xcf: /* DCM abcd [unofficial] */
628 case 0xd3: /* DCM (ab),y [unofficial] */
632 case 0xd7: /* DCM ab,x [unofficial] */
636 case 0xdb: /* DCM abcd,y [unofficial] */
640 case 0xdf: /* DCM abcd,x [unofficial] */
644 case 0xe3: /* INS (ab,x) [unofficial] */
648 case 0xe7: /* INS ab [unofficial] */
652 case 0xef: /* INS abcd [unofficial] */
656 case 0xf3: /* INS (ab),y [unofficial] */
660 case 0xf7: /* INS ab,x [unofficial] */
664 case 0xfb: /* INS abcd,y [unofficial] */
668 case 0xff: /* INS abcd,x [unofficial] */
672 #endif /* ACPU_NO_UNOFFICIAL */
673 case 0x05: /* ORA ab */
677 case 0x06: /* ASL ab */
684 case 0x09: /* ORA #ab */
689 nz
= a
= (a
<< 1) & 0xff;
691 case 0x0d: /* ORA abcd */
695 case 0x0e: /* ASL abcd */
701 case 0x11: /* ORA (ab),y */
706 case 0x15: /* ORA ab,x */
710 case 0x16: /* ASL ab,x */
717 case 0x19: /* ORA abcd,y */
722 case 0x1d: /* ORA abcd,x */
727 case 0x1e: /* ASL abcd,x */
731 case 0x20: /* JSR abcd */
734 pc
= addr
+ (PEEK
<< 8);
736 case 0x21: /* AND (ab,x) */
740 case 0x24: /* BIT ab */
743 vdi
= (vdi
& (D_FLAG
| I_FLAG
)) + (nz
& V_FLAG
);
744 nz
= ((nz
& 0x80) << 1) + (nz
& a
);
746 case 0x25: /* AND ab */
750 case 0x26: /* ROL ab */
758 case 0x29: /* AND #ab */
766 case 0x2c: /* BIT abcd */
769 vdi
= (vdi
& (D_FLAG
| I_FLAG
)) + (nz
& V_FLAG
);
770 nz
= ((nz
& 0x80) << 1) + (nz
& a
);
772 case 0x2d: /* AND abcd */
776 case 0x2e: /* ROL abcd */
782 case 0x31: /* AND (ab),y */
787 case 0x35: /* AND ab,x */
791 case 0x36: /* ROL ab,x */
798 case 0x39: /* AND abcd,y */
803 case 0x3d: /* AND abcd,x */
808 case 0x3e: /* ROL abcd,x */
819 case 0x41: /* EOR (ab,x) */
823 case 0x45: /* EOR ab */
827 case 0x46: /* LSR ab */
834 case 0x49: /* EOR #ab */
841 case 0x4c: /* JMP abcd */
843 pc
= addr
+ (PEEK
<< 8);
845 case 0x4d: /* EOR abcd */
849 case 0x4e: /* LSR abcd */
854 BRANCH((vdi
& V_FLAG
) == 0);
855 case 0x51: /* EOR (ab),y */
860 case 0x55: /* EOR ab,x */
864 case 0x56: /* LSR ab,x */
869 vdi
&= V_FLAG
| D_FLAG
;
872 case 0x59: /* EOR abcd,y */
877 case 0x5d: /* EOR abcd,x */
882 case 0x5e: /* LSR abcd,x */
889 pc
+= (addr
<< 8) + 1;
891 case 0x61: /* ADC (ab,x) */
895 case 0x65: /* ADC ab */
899 case 0x66: /* ROR ab */
907 case 0x69: /* ADC #ab */
912 nz
= (c
<< 7) + (a
>> 1);
916 case 0x6c: /* JMP (abcd) */
918 if ((addr
& 0xff) == 0xff)
919 pc
= (dGetByte(addr
- 0xff) << 8) + dGetByte(addr
);
923 case 0x6d: /* ADC abcd */
927 case 0x6e: /* ROR abcd */
932 BRANCH((vdi
& V_FLAG
) != 0);
933 case 0x71: /* ADC (ab),y */
938 case 0x75: /* ADC ab,x */
942 case 0x76: /* ROR ab,x */
949 case 0x79: /* ADC abcd,y */
954 case 0x7d: /* ADC abcd,x */
959 case 0x7e: /* ROR abcd,x */
963 case 0x81: /* STA (ab,x) */
967 case 0x84: /* STY ab */
971 case 0x85: /* STA ab */
975 case 0x86: /* STX ab */
980 nz
= y
= (y
- 1) & 0xff;
985 case 0x8c: /* STY abcd */
989 case 0x8d: /* STA abcd */
993 case 0x8e: /* STX abcd */
999 case 0x91: /* STA (ab),y */
1003 case 0x94: /* STY ab,x */
1007 case 0x95: /* STA ab,x */
1011 case 0x96: /* STX ab,y */
1015 case 0x98: /* TYA */
1018 case 0x99: /* STA abcd,y */
1022 case 0x9a: /* TXS */
1025 case 0x9d: /* STA abcd,x */
1029 case 0xa0: /* LDY #ab */
1032 case 0xa1: /* LDA (ab,x) */
1036 case 0xa2: /* LDX #ab */
1039 case 0xa4: /* LDY ab */
1043 case 0xa5: /* LDA ab */
1047 case 0xa6: /* LDX ab */
1051 case 0xa8: /* TAY */
1054 case 0xa9: /* LDA #ab */
1057 case 0xaa: /* TAX */
1060 case 0xac: /* LDY abcd */
1064 case 0xad: /* LDA abcd */
1068 case 0xae: /* LDX abcd */
1072 case 0xb0: /* BCS */
1074 case 0xb1: /* LDA (ab),y */
1079 case 0xb4: /* LDY ab,x */
1083 case 0xb5: /* LDA ab,x */
1087 case 0xb6: /* LDX ab,y */
1091 case 0xb8: /* CLV */
1092 vdi
&= D_FLAG
| I_FLAG
;
1094 case 0xb9: /* LDA abcd,y */
1099 case 0xba: /* TSX */
1102 case 0xbc: /* LDY abcd,x */
1107 case 0xbd: /* LDA abcd,x */
1112 case 0xbe: /* LDX abcd,y */
1117 case 0xc0: /* CPY #ab */
1119 c
= (y
>= nz
) ? 1 : 0;
1120 nz
= (y
- nz
) & 0xff;
1122 case 0xc1: /* CMP (ab,x) */
1126 case 0xc4: /* CPY ab */
1130 case 0xc5: /* CMP ab */
1134 case 0xc6: /* DEC ab */
1138 case 0xc8: /* INY */
1139 nz
= y
= (y
+ 1) & 0xff;
1141 case 0xc9: /* CMP #ab */
1143 c
= (a
>= nz
) ? 1 : 0;
1144 nz
= (a
- nz
) & 0xff;
1146 case 0xca: /* DEX */
1147 nz
= x
= (x
- 1) & 0xff;
1149 case 0xcc: /* CPY abcd */
1153 case 0xcd: /* CMP abcd */
1157 case 0xce: /* DEC abcd */
1161 case 0xd0: /* BNE */
1162 BRANCH((nz
& 0xff) != 0);
1163 case 0xd1: /* CMP (ab),y */
1168 case 0xd5: /* CMP ab,x */
1172 case 0xd6: /* DEC ab,x */
1176 case 0xd8: /* CLD */
1177 vdi
&= V_FLAG
| I_FLAG
;
1179 case 0xd9: /* CMP abcd,y */
1184 case 0xdd: /* CMP abcd,x */
1189 case 0xde: /* DEC abcd,x */
1193 case 0xe0: /* CPX #ab */
1195 c
= (x
>= nz
) ? 1 : 0;
1196 nz
= (x
- nz
) & 0xff;
1198 case 0xe1: /* SBC (ab,x) */
1202 case 0xe4: /* CPX ab */
1206 case 0xe5: /* SBC ab */
1210 case 0xe6: /* INC ab */
1214 case 0xe8: /* INX */
1215 nz
= x
= (x
+ 1) & 0xff;
1217 case 0xe9: /* SBC #ab */
1218 case 0xeb: /* SBC #ab [unofficial] */
1222 case 0xea: /* NOP */
1223 case 0x1a: /* NOP [unofficial] */
1230 case 0xec: /* CPX abcd */
1234 case 0xed: /* SBC abcd */
1238 case 0xee: /* INC abcd */
1242 case 0xf0: /* BEQ */
1243 BRANCH((nz
& 0xff) == 0);
1244 case 0xf1: /* SBC (ab),y */
1249 case 0xf5: /* SBC ab,x */
1253 case 0xf6: /* INC ab,x */
1257 case 0xf8: /* SED */
1260 case 0xf9: /* SBC abcd,y */
1265 case 0xfd: /* SBC abcd,x */
1270 case 0xfe: /* INC abcd,x */
1283 ast _ cpu_vdi
= vdi
;
1284 ast _ cycle
-= cycle_limit
;
1285 if (ast _ timer1_cycle
!= NEVER
)
1286 ast _ timer1_cycle
-= cycle_limit
;
1287 if (ast _ timer2_cycle
!= NEVER
)
1288 ast _ timer2_cycle
-= cycle_limit
;
1289 if (ast _ timer4_cycle
!= NEVER
)
1290 ast _ timer4_cycle
-= cycle_limit
;