2 * acpu.c - another 6502 CPU emulator
4 * Copyright (C) 2007-2009 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; \
81 vdi &= D_FLAG | I_FLAG; \
82 if (((a ^ data) & 0x80) == 0 && ((data ^ tmp) & 0x80) != 0) \
84 nz = a = tmp & 0xff; \
90 V(int, tmp) = a - data - 1 + c; \
91 c = (tmp >= 0) ? 1 : 0; \
92 vdi &= D_FLAG | I_FLAG; \
93 if (((a ^ tmp) & 0x80) != 0 && ((a ^ data) & 0x80) != 0) \
95 nz = a = tmp & 0xff; \
98 #else /* ACPU_NO_DECIMAL */
101 if ((vdi & D_FLAG) == 0) { \
103 V(int, tmp) = a + data + c; \
105 vdi &= D_FLAG | I_FLAG; \
106 if (((a ^ data) & 0x80) == 0 && ((data ^ tmp) & 0x80) != 0) \
108 nz = a = tmp & 0xff; \
112 V(int, tmp) = (a & 0x0f) + (data & 0x0f) + c; \
114 tmp = (tmp - 10) | 0x10; \
115 tmp += (a & 0xf0) + (data & 0xf0); \
116 nz = ((tmp & 0x80) << 1) + ((a + data + c) & 0xff); \
117 vdi &= D_FLAG | I_FLAG; \
118 if (((a ^ data) & 0x80) == 0 && ((data ^ tmp) & 0x80) != 0) \
122 c = (tmp > 0xff) ? 1 : 0; \
127 if ((vdi & D_FLAG) == 0) { \
129 V(int, tmp) = a - data - 1 + c; \
130 c = (tmp >= 0) ? 1 : 0; \
131 vdi &= D_FLAG | I_FLAG; \
132 if (((a ^ tmp) & 0x80) != 0 && ((a ^ data) & 0x80) != 0) \
134 nz = a = tmp & 0xff; \
138 V(int, tmp) = a - data - 1 + c; \
139 V(int, al) = (a & 0x0f) - (data & 0x0f) - 1 + c; \
140 V(int, ah) = (a >> 4) - (data >> 4); \
141 if ((al & 0x10) != 0) { \
145 if ((ah & 0x10) != 0) \
147 c = tmp >= 0 ? 1 : 0; \
148 vdi &= D_FLAG | I_FLAG; \
149 if (((a ^ tmp) & 0x80) != 0 && ((a ^ data) & 0x80) != 0) \
152 a = ((ah & 0xf) << 4) + (al & 0x0f); \
155 #endif /* ACPU_NO_DECIMAL */
157 #define zGetByte(addr) dGetByte((addr) & 0xff)
159 #define PEEK dGetByte(pc)
160 #define FETCH dGetByte(pc++)
162 #define ABSOLUTE addr = FETCH; addr += FETCH << 8
163 #define ABSOLUTE_X addr = FETCH; addr = (addr + (FETCH << 8) + x) & 0xffff
164 #define ABSOLUTE_Y addr = FETCH; addr = (addr + (FETCH << 8) + y) & 0xffff
165 #define ZPAGE addr = FETCH
166 #define ZPAGE_X addr = (FETCH + x) & 0xff
167 #define ZPAGE_Y addr = (FETCH + y) & 0xff
168 #define INDIRECT_X addr = (FETCH + x) & 0xff; addr = dGetByte(addr) + (zGetByte(addr + 1) << 8)
169 #define INDIRECT_Y addr = FETCH; addr = (dGetByte(addr) + (zGetByte(addr + 1) << 8) + y) & 0xffff
170 #define NCYCLES_X if ((addr & 0xff) < x) ast _ cycle++
171 #define NCYCLES_Y if ((addr & 0xff) < y) ast _ cycle++
173 #define PL(dest) s = (s + 1) & 0xff; dest = dGetByte(0x0100 + s)
174 #define PLP PL(vdi); nz = ((vdi & 0x80) << 1) + (~vdi & Z_FLAG); c = vdi & 1; vdi &= V_FLAG | D_FLAG | I_FLAG
175 #define PH(data) dPutByte(0x0100 + s, data); s = (s - 1) & 0xff
176 #define PHW(data) PH((data) >> 8); PH(TO_BYTE(data))
177 #define PHP(bflag) PH(((nz | (nz >> 1)) & 0x80) + vdi + ((nz & 0xff) == 0 ? Z_FLAG : 0) + c + bflag)
178 #define PHPB0 PHP(0x20) /* push flags with B flag clear (NMI, IRQ) */
179 #define PHPB1 PHP(0x30) /* push flags with B flag set (PHP, BRK) */
182 #define LDA nz = a = GetByte(addr)
183 #define LDA_ZP nz = a = dGetByte(addr)
184 #define LDX nz = x = GetByte(addr)
185 #define LDX_ZP nz = x = dGetByte(addr)
186 #define LDY nz = y = GetByte(addr)
187 #define LDY_ZP nz = y = dGetByte(addr)
188 #define LAX nz = x = a = GetByte(addr)
189 #define LAX_ZP nz = x = a = dGetByte(addr)
190 #define STA PutByte(addr, a)
191 #define STA_ZP dPutByte(addr, a)
192 #define STX PutByte(addr, x)
193 #define STX_ZP dPutByte(addr, x)
194 #define STY PutByte(addr, y)
195 #define STY_ZP dPutByte(addr, y)
196 #define SAX data = a & x; PutByte(addr, data)
197 #define SAX_ZP data = a & x; dPutByte(addr, data)
198 #define CMP nz = GetByte(addr); c = (a >= nz) ? 1 : 0; nz = (a - nz) & 0xff
199 #define CMP_ZP nz = dGetByte(addr); c = (a >= nz) ? 1 : 0; nz = (a - nz) & 0xff
200 #define CPX nz = GetByte(addr); c = (x >= nz) ? 1 : 0; nz = (x - nz) & 0xff
201 #define CPX_ZP nz = dGetByte(addr); c = (x >= nz) ? 1 : 0; nz = (x - nz) & 0xff
202 #define CPY nz = GetByte(addr); c = (y >= nz) ? 1 : 0; nz = (y - nz) & 0xff
203 #define CPY_ZP nz = dGetByte(addr); c = (y >= nz) ? 1 : 0; nz = (y - nz) & 0xff
204 #define AND nz = a &= GetByte(addr)
205 #define AND_ZP nz = a &= dGetByte(addr)
206 #define ORA nz = a |= GetByte(addr)
207 #define ORA_ZP nz = a |= dGetByte(addr)
208 #define EOR nz = a ^= GetByte(addr)
209 #define EOR_ZP nz = a ^= dGetByte(addr)
210 #define ADC data = GetByte(addr); DO_ADC
211 #define ADC_ZP data = dGetByte(addr); DO_ADC
212 #define SBC data = GetByte(addr); DO_SBC
213 #define SBC_ZP data = dGetByte(addr); DO_SBC
215 #define ASL RMW_GetByte(nz, addr); c = nz >> 7; nz = (nz << 1) & 0xff; PutByte(addr, nz)
216 #define ASL_ZP nz = dGetByte(addr); c = nz >> 7; nz = (nz << 1) & 0xff; dPutByte(addr, nz)
217 #define ROL RMW_GetByte(nz, addr); nz = (nz << 1) + c; c = nz >> 8; nz &= 0xff; PutByte(addr, nz)
218 #define ROL_ZP nz = dGetByte(addr); nz = (nz << 1) + c; c = nz >> 8; nz &= 0xff; dPutByte(addr, nz)
219 #define LSR RMW_GetByte(nz, addr); c = nz & 1; nz >>= 1; PutByte(addr, nz)
220 #define LSR_ZP nz = dGetByte(addr); c = nz & 1; nz >>= 1; dPutByte(addr, nz)
221 #define ROR RMW_GetByte(nz, addr); nz += c << 8; c = nz & 1; nz >>= 1; PutByte(addr, nz)
222 #define ROR_ZP nz = dGetByte(addr) + (c << 8); c = nz & 1; nz >>= 1; dPutByte(addr, nz)
223 #define DEC RMW_GetByte(nz, addr); nz = (nz - 1) & 0xff; PutByte(addr, nz)
224 #define DEC_ZP nz = dGetByte(addr); nz = (nz - 1) & 0xff; dPutByte(addr, nz)
225 #define INC RMW_GetByte(nz, addr); nz = (nz + 1) & 0xff; PutByte(addr, nz)
226 #define INC_ZP nz = dGetByte(addr); nz = (nz + 1) & 0xff; dPutByte(addr, nz)
228 #define ASO ASL; nz = a |= nz
229 #define ASO_ZP ASL_ZP; nz = a |= nz
230 #define RLA ROL; nz = a &= nz
231 #define RLA_ZP ROL_ZP; nz = a &= nz
232 #define LSE LSR; nz = a ^= nz
233 #define LSE_ZP LSR_ZP; nz = a ^= nz
234 #define RRA ROR; data = nz; DO_ADC
235 #define RRA_ZP ROR_ZP; data = nz; DO_ADC
236 #define DCM DEC; c = (a >= nz) ? 1 : 0; nz = (a - nz) & 0xff
237 #define DCM_ZP DEC_ZP; c = (a >= nz) ? 1 : 0; nz = (a - nz) & 0xff
238 #define INS INC; data = nz; DO_SBC
239 #define INS_ZP INC_ZP; data = nz; DO_SBC
241 #define BRANCH(cond) \
243 addr = SBYTE(PEEK); \
246 if ((addr ^ pc) >> 8 != 0) \
256 if ((vdi & I_FLAG) == 0 && ast _ irqst != 0xff) { \
260 pc = dGetWord(0xfffe); \
264 /* Runs 6502 emulation for the specified number of Atari scanlines.
265 Each scanline is 114 cycles of which 9 is taken by ANTIC for memory refresh. */
266 FUNC(void, Cpu_RunScanlines
, (P(ASAP_State PTR
, ast
), P(int, scanlines
)))
268 /* copy registers from ASAP_State to local variables for improved performance */
277 V(int, next_event_cycle
);
287 ast _ next_scanline_cycle
= 114;
288 next_event_cycle
= 114;
289 cycle_limit
= 114 * scanlines
;
290 if (next_event_cycle
> ast _ timer1_cycle
)
291 next_event_cycle
= ast _ timer1_cycle
;
292 if (next_event_cycle
> ast _ timer2_cycle
)
293 next_event_cycle
= ast _ timer2_cycle
;
294 if (next_event_cycle
> ast _ timer4_cycle
)
295 next_event_cycle
= ast _ timer4_cycle
;
296 ast _ nearest_event_cycle
= next_event_cycle
;
302 if (cycle
>= ast _ nearest_event_cycle
) {
303 if (cycle
>= ast _ next_scanline_cycle
) {
304 if (++ast _ scanline_number
== 312)
305 ast _ scanline_number
= 0;
306 ast _ cycle
= cycle
+= 9;
307 ast _ next_scanline_cycle
+= 114;
308 if (--scanlines
<= 0)
311 next_event_cycle
= ast _ next_scanline_cycle
;
312 #define CHECK_TIMER_IRQ(ch) \
313 if (cycle >= ast _ timer##ch##_cycle) { \
314 ast _ irqst &= ~ch; \
315 ast _ timer##ch##_cycle = NEVER; \
317 else if (next_event_cycle > ast _ timer##ch##_cycle) \
318 next_event_cycle = ast _ timer##ch##_cycle;
322 ast _ nearest_event_cycle
= next_event_cycle
;
327 trace_cpu(ast
, pc
, a
, x
, y
, s
, nz
, vdi
, c
);
330 ast _ cycle
+= opcode_cycles
[data
];
337 pc
= dGetWord(0xfffe);
339 case 0x01: /* ORA (ab,x) */
343 case 0x02: /* CIM [unofficial] */
355 ast _ scanline_number
= (ast _ scanline_number
+ scanlines
- 1) % 312;
357 ast _ cycle
= cycle_limit
;
359 #ifndef ACPU_NO_UNOFFICIAL
360 case 0x03: /* ASO (ab,x) [unofficial] */
364 case 0x04: /* NOP ab [unofficial] */
367 case 0x14: /* NOP ab,x [unofficial] */
373 case 0x80: /* NOP #ab [unofficial] */
380 case 0x07: /* ASO ab [unofficial] */
384 case 0x0b: /* ANC #ab [unofficial] */
389 case 0x0c: /* NOP abcd [unofficial] */
392 case 0x0f: /* ASO abcd [unofficial] */
396 case 0x13: /* ASO (ab),y [unofficial] */
400 case 0x17: /* ASO ab,x [unofficial] */
404 case 0x1b: /* ASO abcd,y [unofficial] */
408 case 0x1c: /* NOP abcd,x [unofficial] */
414 if (FETCH
+ x
>= 0x100)
418 case 0x1f: /* ASO abcd,x [unofficial] */
422 case 0x23: /* RLA (ab,x) [unofficial] */
426 case 0x27: /* RLA ab [unofficial] */
430 case 0x2f: /* RLA abcd [unofficial] */
434 case 0x33: /* RLA (ab),y [unofficial] */
438 case 0x37: /* RLA ab,x [unofficial] */
442 case 0x3b: /* RLA abcd,y [unofficial] */
446 case 0x3f: /* RLA abcd,x [unofficial] */
450 case 0x43: /* LSE (ab,x) [unofficial] */
454 case 0x47: /* LSE ab [unofficial] */
458 case 0x4b: /* ALR #ab [unofficial] */
463 case 0x4f: /* LSE abcd [unofficial] */
467 case 0x53: /* LSE (ab),y [unofficial] */
471 case 0x57: /* LSE ab,x [unofficial] */
475 case 0x5b: /* LSE abcd,y [unofficial] */
479 case 0x5f: /* LSE abcd,x [unofficial] */
483 case 0x63: /* RRA (ab,x) [unofficial] */
487 case 0x67: /* RRA ab [unofficial] */
491 case 0x6b: /* ARR #ab [unofficial] */
493 nz
= a
= (data
>> 1) + (c
<< 7);
494 vdi
= (vdi
& (D_FLAG
| I_FLAG
)) + ((a
^ data
) & V_FLAG
);
495 #ifdef ACPU_NO_DECIMAL
498 if ((vdi
& D_FLAG
) == 0)
501 if ((data
& 0xf) >= 5)
502 a
= (a
& 0xf0) + ((a
+ 6) & 0xf);
504 a
= (a
+ 0x60) & 0xff;
512 case 0x6f: /* RRA abcd [unofficial] */
516 case 0x73: /* RRA (ab),y [unofficial] */
520 case 0x77: /* RRA ab,x [unofficial] */
524 case 0x7b: /* RRA abcd,y [unofficial] */
528 case 0x7f: /* RRA abcd,x [unofficial] */
532 case 0x83: /* SAX (ab,x) [unofficial] */
536 case 0x87: /* SAX ab [unofficial] */
540 case 0x8b: /* ANE #ab [unofficial] */
546 case 0x8f: /* SAX abcd [unofficial] */
550 case 0x93: /* SHA (ab),y [unofficial, unstable] */
552 data
= zGetByte(addr
+ 1);
553 addr
= (dGetByte(addr
) + (data
<< 8) + y
) & 0xffff;
554 data
= a
& x
& (data
+ 1);
557 case 0x97: /* SAX ab,y [unofficial] */
561 case 0x9b: /* SHS abcd,y [unofficial, unstable] */
562 /* S seems to be stable, only memory values vary */
565 addr
= (addr
+ (data
<< 8) + y
) & 0xffff;
567 data
= s
& (data
+ 1);
570 case 0x9c: /* SHY abcd,x [unofficial] */
573 addr
= (addr
+ (data
<< 8) + x
) & 0xffff;
574 data
= y
& (data
+ 1);
577 case 0x9e: /* SHX abcd,y [unofficial] */
580 addr
= (addr
+ (data
<< 8) + y
) & 0xffff;
581 data
= x
& (data
+ 1);
584 case 0x9f: /* SHA abcd,y [unofficial, unstable] */
587 addr
= (addr
+ (data
<< 8) + y
) & 0xffff;
588 data
= a
& x
& (data
+ 1);
591 case 0xa3: /* LAX (ab,x) [unofficial] */
595 case 0xa7: /* LAX ab [unofficial] */
599 case 0xab: /* ANX #ab [unofficial] */
602 case 0xaf: /* LAX abcd [unofficial] */
606 case 0xb3: /* LAX (ab),y [unofficial] */
611 case 0xb7: /* LAX ab,y [unofficial] */
615 case 0xbb: /* LAS abcd,y [unofficial] */
618 nz
= x
= a
= s
&= GetByte(addr
);
620 case 0xbf: /* LAX abcd,y [unofficial] */
625 case 0xc3: /* DCM (ab,x) [unofficial] */
629 case 0xc7: /* DCM ab [unofficial] */
633 case 0xcb: /* SBX #ab [unofficial] */
636 c
= (x
>= nz
) ? 1 : 0;
637 nz
= x
= (x
- nz
) & 0xff;
639 case 0xcf: /* DCM abcd [unofficial] */
643 case 0xd3: /* DCM (ab),y [unofficial] */
647 case 0xd7: /* DCM ab,x [unofficial] */
651 case 0xdb: /* DCM abcd,y [unofficial] */
655 case 0xdf: /* DCM abcd,x [unofficial] */
659 case 0xe3: /* INS (ab,x) [unofficial] */
663 case 0xe7: /* INS ab [unofficial] */
667 case 0xef: /* INS abcd [unofficial] */
671 case 0xf3: /* INS (ab),y [unofficial] */
675 case 0xf7: /* INS ab,x [unofficial] */
679 case 0xfb: /* INS abcd,y [unofficial] */
683 case 0xff: /* INS abcd,x [unofficial] */
687 #endif /* ACPU_NO_UNOFFICIAL */
688 case 0x05: /* ORA ab */
692 case 0x06: /* ASL ab */
699 case 0x09: /* ORA #ab */
704 nz
= a
= (a
<< 1) & 0xff;
706 case 0x0d: /* ORA abcd */
710 case 0x0e: /* ASL abcd */
716 case 0x11: /* ORA (ab),y */
721 case 0x15: /* ORA ab,x */
725 case 0x16: /* ASL ab,x */
732 case 0x19: /* ORA abcd,y */
737 case 0x1d: /* ORA abcd,x */
742 case 0x1e: /* ASL abcd,x */
746 case 0x20: /* JSR abcd */
749 pc
= addr
+ (PEEK
<< 8);
751 case 0x21: /* AND (ab,x) */
755 case 0x24: /* BIT ab */
758 vdi
= (vdi
& (D_FLAG
| I_FLAG
)) + (nz
& V_FLAG
);
759 nz
= ((nz
& 0x80) << 1) + (nz
& a
);
761 case 0x25: /* AND ab */
765 case 0x26: /* ROL ab */
773 case 0x29: /* AND #ab */
781 case 0x2c: /* BIT abcd */
784 vdi
= (vdi
& (D_FLAG
| I_FLAG
)) + (nz
& V_FLAG
);
785 nz
= ((nz
& 0x80) << 1) + (nz
& a
);
787 case 0x2d: /* AND abcd */
791 case 0x2e: /* ROL abcd */
797 case 0x31: /* AND (ab),y */
802 case 0x35: /* AND ab,x */
806 case 0x36: /* ROL ab,x */
813 case 0x39: /* AND abcd,y */
818 case 0x3d: /* AND abcd,x */
823 case 0x3e: /* ROL abcd,x */
834 case 0x41: /* EOR (ab,x) */
838 case 0x45: /* EOR ab */
842 case 0x46: /* LSR ab */
849 case 0x49: /* EOR #ab */
856 case 0x4c: /* JMP abcd */
858 pc
= addr
+ (PEEK
<< 8);
860 case 0x4d: /* EOR abcd */
864 case 0x4e: /* LSR abcd */
869 BRANCH((vdi
& V_FLAG
) == 0);
870 case 0x51: /* EOR (ab),y */
875 case 0x55: /* EOR ab,x */
879 case 0x56: /* LSR ab,x */
884 vdi
&= V_FLAG
| D_FLAG
;
887 case 0x59: /* EOR abcd,y */
892 case 0x5d: /* EOR abcd,x */
897 case 0x5e: /* LSR abcd,x */
904 pc
+= (addr
<< 8) + 1;
906 case 0x61: /* ADC (ab,x) */
910 case 0x65: /* ADC ab */
914 case 0x66: /* ROR ab */
922 case 0x69: /* ADC #ab */
927 nz
= (c
<< 7) + (a
>> 1);
931 case 0x6c: /* JMP (abcd) */
933 if ((addr
& 0xff) == 0xff)
934 pc
= (dGetByte(addr
- 0xff) << 8) + dGetByte(addr
);
938 case 0x6d: /* ADC abcd */
942 case 0x6e: /* ROR abcd */
947 BRANCH((vdi
& V_FLAG
) != 0);
948 case 0x71: /* ADC (ab),y */
953 case 0x75: /* ADC ab,x */
957 case 0x76: /* ROR ab,x */
964 case 0x79: /* ADC abcd,y */
969 case 0x7d: /* ADC abcd,x */
974 case 0x7e: /* ROR abcd,x */
978 case 0x81: /* STA (ab,x) */
982 case 0x84: /* STY ab */
986 case 0x85: /* STA ab */
990 case 0x86: /* STX ab */
995 nz
= y
= (y
- 1) & 0xff;
1000 case 0x8c: /* STY abcd */
1004 case 0x8d: /* STA abcd */
1008 case 0x8e: /* STX abcd */
1012 case 0x90: /* BCC */
1014 case 0x91: /* STA (ab),y */
1018 case 0x94: /* STY ab,x */
1022 case 0x95: /* STA ab,x */
1026 case 0x96: /* STX ab,y */
1030 case 0x98: /* TYA */
1033 case 0x99: /* STA abcd,y */
1037 case 0x9a: /* TXS */
1040 case 0x9d: /* STA abcd,x */
1044 case 0xa0: /* LDY #ab */
1047 case 0xa1: /* LDA (ab,x) */
1051 case 0xa2: /* LDX #ab */
1054 case 0xa4: /* LDY ab */
1058 case 0xa5: /* LDA ab */
1062 case 0xa6: /* LDX ab */
1066 case 0xa8: /* TAY */
1069 case 0xa9: /* LDA #ab */
1072 case 0xaa: /* TAX */
1075 case 0xac: /* LDY abcd */
1079 case 0xad: /* LDA abcd */
1083 case 0xae: /* LDX abcd */
1087 case 0xb0: /* BCS */
1089 case 0xb1: /* LDA (ab),y */
1094 case 0xb4: /* LDY ab,x */
1098 case 0xb5: /* LDA ab,x */
1102 case 0xb6: /* LDX ab,y */
1106 case 0xb8: /* CLV */
1107 vdi
&= D_FLAG
| I_FLAG
;
1109 case 0xb9: /* LDA abcd,y */
1114 case 0xba: /* TSX */
1117 case 0xbc: /* LDY abcd,x */
1122 case 0xbd: /* LDA abcd,x */
1127 case 0xbe: /* LDX abcd,y */
1132 case 0xc0: /* CPY #ab */
1134 c
= (y
>= nz
) ? 1 : 0;
1135 nz
= (y
- nz
) & 0xff;
1137 case 0xc1: /* CMP (ab,x) */
1141 case 0xc4: /* CPY ab */
1145 case 0xc5: /* CMP ab */
1149 case 0xc6: /* DEC ab */
1153 case 0xc8: /* INY */
1154 nz
= y
= (y
+ 1) & 0xff;
1156 case 0xc9: /* CMP #ab */
1158 c
= (a
>= nz
) ? 1 : 0;
1159 nz
= (a
- nz
) & 0xff;
1161 case 0xca: /* DEX */
1162 nz
= x
= (x
- 1) & 0xff;
1164 case 0xcc: /* CPY abcd */
1168 case 0xcd: /* CMP abcd */
1172 case 0xce: /* DEC abcd */
1176 case 0xd0: /* BNE */
1177 BRANCH((nz
& 0xff) != 0);
1178 case 0xd1: /* CMP (ab),y */
1183 case 0xd5: /* CMP ab,x */
1187 case 0xd6: /* DEC ab,x */
1191 case 0xd8: /* CLD */
1192 vdi
&= V_FLAG
| I_FLAG
;
1194 case 0xd9: /* CMP abcd,y */
1199 case 0xdd: /* CMP abcd,x */
1204 case 0xde: /* DEC abcd,x */
1208 case 0xe0: /* CPX #ab */
1210 c
= (x
>= nz
) ? 1 : 0;
1211 nz
= (x
- nz
) & 0xff;
1213 case 0xe1: /* SBC (ab,x) */
1217 case 0xe4: /* CPX ab */
1221 case 0xe5: /* SBC ab */
1225 case 0xe6: /* INC ab */
1229 case 0xe8: /* INX */
1230 nz
= x
= (x
+ 1) & 0xff;
1232 case 0xe9: /* SBC #ab */
1233 case 0xeb: /* SBC #ab [unofficial] */
1237 case 0xea: /* NOP */
1238 case 0x1a: /* NOP [unofficial] */
1245 case 0xec: /* CPX abcd */
1249 case 0xed: /* SBC abcd */
1253 case 0xee: /* INC abcd */
1257 case 0xf0: /* BEQ */
1258 BRANCH((nz
& 0xff) == 0);
1259 case 0xf1: /* SBC (ab),y */
1264 case 0xf5: /* SBC ab,x */
1268 case 0xf6: /* INC ab,x */
1272 case 0xf8: /* SED */
1275 case 0xf9: /* SBC abcd,y */
1280 case 0xfd: /* SBC abcd,x */
1285 case 0xfe: /* INC abcd,x */
1298 ast _ cpu_vdi
= vdi
;
1299 ast _ cycle
-= cycle_limit
;
1300 if (ast _ timer1_cycle
!= NEVER
)
1301 ast _ timer1_cycle
-= cycle_limit
;
1302 if (ast _ timer2_cycle
!= NEVER
)
1303 ast _ timer2_cycle
-= cycle_limit
;
1304 if (ast _ timer4_cycle
!= NEVER
)
1305 ast _ timer4_cycle
-= cycle_limit
;