diff options
Diffstat (limited to 'lib/rbcodec/codecs/libasap/acpu.c')
-rw-r--r-- | lib/rbcodec/codecs/libasap/acpu.c | 1291 |
1 files changed, 1291 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/libasap/acpu.c b/lib/rbcodec/codecs/libasap/acpu.c new file mode 100644 index 0000000000..0fd5988b83 --- /dev/null +++ b/lib/rbcodec/codecs/libasap/acpu.c | |||
@@ -0,0 +1,1291 @@ | |||
1 | /* | ||
2 | * acpu.c - another 6502 CPU emulator | ||
3 | * | ||
4 | * Copyright (C) 2007-2010 Piotr Fusik | ||
5 | * | ||
6 | * This file is part of ASAP (Another Slight Atari Player), | ||
7 | * see http://asap.sourceforge.net | ||
8 | * | ||
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. | ||
13 | * | ||
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. | ||
18 | * | ||
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 | ||
22 | */ | ||
23 | |||
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. | ||
30 | c is either 0 or 1. | ||
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 | ||
36 | (not 7th) bit of nz. | ||
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. | ||
39 | |||
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. | ||
45 | |||
46 | Emulation of POKEY timer interrupts is included. | ||
47 | |||
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. */ | ||
51 | |||
52 | #include "asap_internal.h" | ||
53 | |||
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 */ | ||
72 | END_CONST_ARRAY; | ||
73 | |||
74 | #ifdef ACPU_NO_DECIMAL | ||
75 | |||
76 | #define DO_ADC \ | ||
77 | { \ | ||
78 | /* binary mode */ \ | ||
79 | V(int, tmp) = a + data + c; \ | ||
80 | vdi = (vdi & (D_FLAG | I_FLAG)) + (((~(data ^ a) & (a ^ tmp)) >> 1) & V_FLAG); \ | ||
81 | c = tmp >> 8; \ | ||
82 | nz = a = tmp & 0xff; \ | ||
83 | } | ||
84 | |||
85 | #define DO_SBC \ | ||
86 | { \ | ||
87 | /* binary mode */ \ | ||
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; \ | ||
92 | } | ||
93 | |||
94 | #else /* ACPU_NO_DECIMAL */ | ||
95 | |||
96 | #define DO_ADC \ | ||
97 | { \ | ||
98 | V(int, tmp) = a + data + c; \ | ||
99 | nz = tmp & 0xff; \ | ||
100 | if ((vdi & D_FLAG) == 0) { \ | ||
101 | /* binary mode */ \ | ||
102 | vdi = (vdi & (D_FLAG | I_FLAG)) + (((~(data ^ a) & (a ^ tmp)) >> 1) & V_FLAG); \ | ||
103 | c = tmp >> 8; \ | ||
104 | a = nz; \ | ||
105 | } \ | ||
106 | else { \ | ||
107 | /* decimal mode */ \ | ||
108 | V(int, al) = (a & 0x0f) + (data & 0x0f) + c; \ | ||
109 | if (al >= 10) \ | ||
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); \ | ||
113 | if (tmp >= 0xa0) { \ | ||
114 | c = 1; \ | ||
115 | a = (tmp + 0x60) & 0xff; \ | ||
116 | } \ | ||
117 | else { \ | ||
118 | c = 0; \ | ||
119 | a = tmp; \ | ||
120 | } \ | ||
121 | } \ | ||
122 | } | ||
123 | |||
124 | #define DO_SBC \ | ||
125 | {\ | ||
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) { \ | ||
132 | /* decimal mode */ \ | ||
133 | if (al < 0) \ | ||
134 | a += (al < -10) ? 10 : -6; \ | ||
135 | if (c == 0) \ | ||
136 | a = (a - 0x60) & 0xff; \ | ||
137 | } \ | ||
138 | } | ||
139 | |||
140 | #endif /* ACPU_NO_DECIMAL */ | ||
141 | |||
142 | #define zGetByte(addr) dGetByte((addr) & 0xff) | ||
143 | |||
144 | #define PEEK dGetByte(pc) | ||
145 | #define FETCH dGetByte(pc++) | ||
146 | |||
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++ | ||
157 | |||
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) */ | ||
165 | #define PHPC PHW(pc) | ||
166 | |||
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 | ||
199 | |||
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) | ||
212 | |||
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 | ||
225 | |||
226 | #define BRANCH(cond) \ | ||
227 | if (cond) { \ | ||
228 | addr = SBYTE(PEEK); \ | ||
229 | pc++; \ | ||
230 | addr += pc; \ | ||
231 | if ((addr ^ pc) >> 8 != 0) \ | ||
232 | ast _ cycle++; \ | ||
233 | ast _ cycle++; \ | ||
234 | pc = addr; \ | ||
235 | break; \ | ||
236 | } \ | ||
237 | pc++; \ | ||
238 | break | ||
239 | |||
240 | #define CHECK_IRQ \ | ||
241 | if ((vdi & I_FLAG) == 0 && ast _ irqst != 0xff) { \ | ||
242 | PHPC; \ | ||
243 | PHPB0; \ | ||
244 | vdi |= I_FLAG; \ | ||
245 | pc = dGetWord(0xfffe); \ | ||
246 | ast _ cycle += 7; \ | ||
247 | } | ||
248 | |||
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))) | ||
252 | { | ||
253 | /* copy registers from ASAP_State to local variables for improved performance */ | ||
254 | V(int, pc); | ||
255 | V(int, nz); | ||
256 | V(int, a); | ||
257 | V(int, x); | ||
258 | V(int, y); | ||
259 | V(int, c); | ||
260 | V(int, s); | ||
261 | V(int, vdi); | ||
262 | V(int, next_event_cycle); | ||
263 | V(int, cycle_limit); | ||
264 | pc = ast _ cpu_pc; | ||
265 | nz = ast _ cpu_nz; | ||
266 | a = ast _ cpu_a; | ||
267 | x = ast _ cpu_x; | ||
268 | y = ast _ cpu_y; | ||
269 | c = ast _ cpu_c; | ||
270 | s = ast _ cpu_s; | ||
271 | vdi = ast _ cpu_vdi; | ||
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; | ||
282 | for (;;) { | ||
283 | V(int, cycle); | ||
284 | V(int, addr); | ||
285 | V(int, data); | ||
286 | cycle = ast _ 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) | ||
294 | break; | ||
295 | } | ||
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; \ | ||
301 | } \ | ||
302 | else if (next_event_cycle > ast _ timer##ch##_cycle) \ | ||
303 | next_event_cycle = ast _ timer##ch##_cycle; | ||
304 | CHECK_TIMER_IRQ(1); | ||
305 | CHECK_TIMER_IRQ(2); | ||
306 | CHECK_TIMER_IRQ(4); | ||
307 | ast _ nearest_event_cycle = next_event_cycle; | ||
308 | CHECK_IRQ; | ||
309 | } | ||
310 | #ifdef ASAPSCAN | ||
311 | if (cpu_trace != 0) | ||
312 | trace_cpu(ast, pc, a, x, y, s, nz, vdi, c); | ||
313 | #endif | ||
314 | data = FETCH; | ||
315 | ast _ cycle += opcode_cycles[data]; | ||
316 | switch (data) { | ||
317 | case 0x00: /* BRK */ | ||
318 | pc++; | ||
319 | PHPC; | ||
320 | PHPB1; | ||
321 | vdi |= I_FLAG; | ||
322 | pc = dGetWord(0xfffe); | ||
323 | break; | ||
324 | case 0x01: /* ORA (ab,x) */ | ||
325 | INDIRECT_X; | ||
326 | ORA; | ||
327 | break; | ||
328 | case 0x02: /* CIM [unofficial] */ | ||
329 | case 0x12: | ||
330 | case 0x22: | ||
331 | case 0x32: | ||
332 | case 0x42: | ||
333 | case 0x52: | ||
334 | case 0x62: | ||
335 | case 0x72: | ||
336 | case 0x92: | ||
337 | case 0xb2: | ||
338 | case 0xd2: | ||
339 | case 0xf2: | ||
340 | ast _ scanline_number = (ast _ scanline_number + scanlines - 1) % (ast _ module_info->ntsc ? 262 : 312); | ||
341 | scanlines = 1; | ||
342 | ast _ cycle = cycle_limit; | ||
343 | break; | ||
344 | #ifndef ACPU_NO_UNOFFICIAL | ||
345 | case 0x03: /* ASO (ab,x) [unofficial] */ | ||
346 | INDIRECT_X; | ||
347 | ASO; | ||
348 | break; | ||
349 | case 0x04: /* NOP ab [unofficial] */ | ||
350 | case 0x44: | ||
351 | case 0x64: | ||
352 | case 0x14: /* NOP ab,x [unofficial] */ | ||
353 | case 0x34: | ||
354 | case 0x54: | ||
355 | case 0x74: | ||
356 | case 0xd4: | ||
357 | case 0xf4: | ||
358 | case 0x80: /* NOP #ab [unofficial] */ | ||
359 | case 0x82: | ||
360 | case 0x89: | ||
361 | case 0xc2: | ||
362 | case 0xe2: | ||
363 | pc++; | ||
364 | break; | ||
365 | case 0x07: /* ASO ab [unofficial] */ | ||
366 | ZPAGE; | ||
367 | ASO_ZP; | ||
368 | break; | ||
369 | case 0x0b: /* ANC #ab [unofficial] */ | ||
370 | case 0x2b: | ||
371 | nz = a &= FETCH; | ||
372 | c = nz >> 7; | ||
373 | break; | ||
374 | case 0x0c: /* NOP abcd [unofficial] */ | ||
375 | pc += 2; | ||
376 | break; | ||
377 | case 0x0f: /* ASO abcd [unofficial] */ | ||
378 | ABSOLUTE; | ||
379 | ASO; | ||
380 | break; | ||
381 | case 0x13: /* ASO (ab),y [unofficial] */ | ||
382 | INDIRECT_Y; | ||
383 | ASO; | ||
384 | break; | ||
385 | case 0x17: /* ASO ab,x [unofficial] */ | ||
386 | ZPAGE_X; | ||
387 | ASO_ZP; | ||
388 | break; | ||
389 | case 0x1b: /* ASO abcd,y [unofficial] */ | ||
390 | ABSOLUTE_Y; | ||
391 | ASO; | ||
392 | break; | ||
393 | case 0x1c: /* NOP abcd,x [unofficial] */ | ||
394 | case 0x3c: | ||
395 | case 0x5c: | ||
396 | case 0x7c: | ||
397 | case 0xdc: | ||
398 | case 0xfc: | ||
399 | if (FETCH + x >= 0x100) | ||
400 | ast _ cycle++; | ||
401 | pc++; | ||
402 | break; | ||
403 | case 0x1f: /* ASO abcd,x [unofficial] */ | ||
404 | ABSOLUTE_X; | ||
405 | ASO; | ||
406 | break; | ||
407 | case 0x23: /* RLA (ab,x) [unofficial] */ | ||
408 | INDIRECT_X; | ||
409 | RLA; | ||
410 | break; | ||
411 | case 0x27: /* RLA ab [unofficial] */ | ||
412 | ZPAGE; | ||
413 | RLA_ZP; | ||
414 | break; | ||
415 | case 0x2f: /* RLA abcd [unofficial] */ | ||
416 | ABSOLUTE; | ||
417 | RLA; | ||
418 | break; | ||
419 | case 0x33: /* RLA (ab),y [unofficial] */ | ||
420 | INDIRECT_Y; | ||
421 | RLA; | ||
422 | break; | ||
423 | case 0x37: /* RLA ab,x [unofficial] */ | ||
424 | ZPAGE_X; | ||
425 | RLA_ZP; | ||
426 | break; | ||
427 | case 0x3b: /* RLA abcd,y [unofficial] */ | ||
428 | ABSOLUTE_Y; | ||
429 | RLA; | ||
430 | break; | ||
431 | case 0x3f: /* RLA abcd,x [unofficial] */ | ||
432 | ABSOLUTE_X; | ||
433 | RLA; | ||
434 | break; | ||
435 | case 0x43: /* LSE (ab,x) [unofficial] */ | ||
436 | INDIRECT_X; | ||
437 | LSE; | ||
438 | break; | ||
439 | case 0x47: /* LSE ab [unofficial] */ | ||
440 | ZPAGE; | ||
441 | LSE_ZP; | ||
442 | break; | ||
443 | case 0x4b: /* ALR #ab [unofficial] */ | ||
444 | a &= FETCH; | ||
445 | c = a & 1; | ||
446 | nz = a >>= 1; | ||
447 | break; | ||
448 | case 0x4f: /* LSE abcd [unofficial] */ | ||
449 | ABSOLUTE; | ||
450 | LSE; | ||
451 | break; | ||
452 | case 0x53: /* LSE (ab),y [unofficial] */ | ||
453 | INDIRECT_Y; | ||
454 | LSE; | ||
455 | break; | ||
456 | case 0x57: /* LSE ab,x [unofficial] */ | ||
457 | ZPAGE_X; | ||
458 | LSE_ZP; | ||
459 | break; | ||
460 | case 0x5b: /* LSE abcd,y [unofficial] */ | ||
461 | ABSOLUTE_Y; | ||
462 | LSE; | ||
463 | break; | ||
464 | case 0x5f: /* LSE abcd,x [unofficial] */ | ||
465 | ABSOLUTE_X; | ||
466 | LSE; | ||
467 | break; | ||
468 | case 0x63: /* RRA (ab,x) [unofficial] */ | ||
469 | INDIRECT_X; | ||
470 | RRA; | ||
471 | break; | ||
472 | case 0x67: /* RRA ab [unofficial] */ | ||
473 | ZPAGE; | ||
474 | RRA_ZP; | ||
475 | break; | ||
476 | case 0x6b: /* ARR #ab [unofficial] */ | ||
477 | data = a & FETCH; | ||
478 | nz = a = (data >> 1) + (c << 7); | ||
479 | vdi = (vdi & (D_FLAG | I_FLAG)) + ((a ^ data) & V_FLAG); | ||
480 | #ifdef ACPU_NO_DECIMAL | ||
481 | c = data >> 7; | ||
482 | #else | ||
483 | if ((vdi & D_FLAG) == 0) | ||
484 | c = data >> 7; | ||
485 | else { | ||
486 | if ((data & 0xf) >= 5) | ||
487 | a = (a & 0xf0) + ((a + 6) & 0xf); | ||
488 | if (data >= 0x50) { | ||
489 | a = (a + 0x60) & 0xff; | ||
490 | c = 1; | ||
491 | } | ||
492 | else | ||
493 | c = 0; | ||
494 | } | ||
495 | #endif | ||
496 | break; | ||
497 | case 0x6f: /* RRA abcd [unofficial] */ | ||
498 | ABSOLUTE; | ||
499 | RRA; | ||
500 | break; | ||
501 | case 0x73: /* RRA (ab),y [unofficial] */ | ||
502 | INDIRECT_Y; | ||
503 | RRA; | ||
504 | break; | ||
505 | case 0x77: /* RRA ab,x [unofficial] */ | ||
506 | ZPAGE_X; | ||
507 | RRA_ZP; | ||
508 | break; | ||
509 | case 0x7b: /* RRA abcd,y [unofficial] */ | ||
510 | ABSOLUTE_Y; | ||
511 | RRA; | ||
512 | break; | ||
513 | case 0x7f: /* RRA abcd,x [unofficial] */ | ||
514 | ABSOLUTE_X; | ||
515 | RRA; | ||
516 | break; | ||
517 | case 0x83: /* SAX (ab,x) [unofficial] */ | ||
518 | INDIRECT_X; | ||
519 | SAX; | ||
520 | break; | ||
521 | case 0x87: /* SAX ab [unofficial] */ | ||
522 | ZPAGE; | ||
523 | SAX_ZP; | ||
524 | break; | ||
525 | case 0x8b: /* ANE #ab [unofficial] */ | ||
526 | data = FETCH; | ||
527 | a &= x; | ||
528 | nz = a & data; | ||
529 | a &= data | 0xef; | ||
530 | break; | ||
531 | case 0x8f: /* SAX abcd [unofficial] */ | ||
532 | ABSOLUTE; | ||
533 | SAX; | ||
534 | break; | ||
535 | case 0x93: /* SHA (ab),y [unofficial, unstable] */ | ||
536 | ZPAGE; | ||
537 | data = zGetByte(addr + 1); | ||
538 | addr = (dGetByte(addr) + (data << 8) + y) & 0xffff; | ||
539 | data = a & x & (data + 1); | ||
540 | PutByte(addr, data); | ||
541 | break; | ||
542 | case 0x97: /* SAX ab,y [unofficial] */ | ||
543 | ZPAGE_Y; | ||
544 | SAX_ZP; | ||
545 | break; | ||
546 | case 0x9b: /* SHS abcd,y [unofficial, unstable] */ | ||
547 | /* S seems to be stable, only memory values vary */ | ||
548 | addr = FETCH; | ||
549 | data = FETCH; | ||
550 | addr = (addr + (data << 8) + y) & 0xffff; | ||
551 | s = a & x; | ||
552 | data = s & (data + 1); | ||
553 | PutByte(addr, data); | ||
554 | break; | ||
555 | case 0x9c: /* SHY abcd,x [unofficial] */ | ||
556 | addr = FETCH; | ||
557 | data = FETCH; | ||
558 | addr = (addr + (data << 8) + x) & 0xffff; | ||
559 | data = y & (data + 1); | ||
560 | PutByte(addr, data); | ||
561 | break; | ||
562 | case 0x9e: /* SHX abcd,y [unofficial] */ | ||
563 | addr = FETCH; | ||
564 | data = FETCH; | ||
565 | addr = (addr + (data << 8) + y) & 0xffff; | ||
566 | data = x & (data + 1); | ||
567 | PutByte(addr, data); | ||
568 | break; | ||
569 | case 0x9f: /* SHA abcd,y [unofficial, unstable] */ | ||
570 | addr = FETCH; | ||
571 | data = FETCH; | ||
572 | addr = (addr + (data << 8) + y) & 0xffff; | ||
573 | data = a & x & (data + 1); | ||
574 | PutByte(addr, data); | ||
575 | break; | ||
576 | case 0xa3: /* LAX (ab,x) [unofficial] */ | ||
577 | INDIRECT_X; | ||
578 | LAX; | ||
579 | break; | ||
580 | case 0xa7: /* LAX ab [unofficial] */ | ||
581 | ZPAGE; | ||
582 | LAX_ZP; | ||
583 | break; | ||
584 | case 0xab: /* ANX #ab [unofficial] */ | ||
585 | nz = x = a &= FETCH; | ||
586 | break; | ||
587 | case 0xaf: /* LAX abcd [unofficial] */ | ||
588 | ABSOLUTE; | ||
589 | LAX; | ||
590 | break; | ||
591 | case 0xb3: /* LAX (ab),y [unofficial] */ | ||
592 | INDIRECT_Y; | ||
593 | NCYCLES_Y; | ||
594 | LAX; | ||
595 | break; | ||
596 | case 0xb7: /* LAX ab,y [unofficial] */ | ||
597 | ZPAGE_Y; | ||
598 | LAX_ZP; | ||
599 | break; | ||
600 | case 0xbb: /* LAS abcd,y [unofficial] */ | ||
601 | ABSOLUTE_Y; | ||
602 | NCYCLES_Y; | ||
603 | nz = x = a = s &= GetByte(addr); | ||
604 | break; | ||
605 | case 0xbf: /* LAX abcd,y [unofficial] */ | ||
606 | ABSOLUTE_Y; | ||
607 | NCYCLES_Y; | ||
608 | LAX; | ||
609 | break; | ||
610 | case 0xc3: /* DCM (ab,x) [unofficial] */ | ||
611 | INDIRECT_X; | ||
612 | DCM; | ||
613 | break; | ||
614 | case 0xc7: /* DCM ab [unofficial] */ | ||
615 | ZPAGE; | ||
616 | DCM_ZP; | ||
617 | break; | ||
618 | case 0xcb: /* SBX #ab [unofficial] */ | ||
619 | nz = FETCH; | ||
620 | x &= a; | ||
621 | c = (x >= nz) ? 1 : 0; | ||
622 | nz = x = (x - nz) & 0xff; | ||
623 | break; | ||
624 | case 0xcf: /* DCM abcd [unofficial] */ | ||
625 | ABSOLUTE; | ||
626 | DCM; | ||
627 | break; | ||
628 | case 0xd3: /* DCM (ab),y [unofficial] */ | ||
629 | INDIRECT_Y; | ||
630 | DCM; | ||
631 | break; | ||
632 | case 0xd7: /* DCM ab,x [unofficial] */ | ||
633 | ZPAGE_X; | ||
634 | DCM_ZP; | ||
635 | break; | ||
636 | case 0xdb: /* DCM abcd,y [unofficial] */ | ||
637 | ABSOLUTE_Y; | ||
638 | DCM; | ||
639 | break; | ||
640 | case 0xdf: /* DCM abcd,x [unofficial] */ | ||
641 | ABSOLUTE_X; | ||
642 | DCM; | ||
643 | break; | ||
644 | case 0xe3: /* INS (ab,x) [unofficial] */ | ||
645 | INDIRECT_X; | ||
646 | INS; | ||
647 | break; | ||
648 | case 0xe7: /* INS ab [unofficial] */ | ||
649 | ZPAGE; | ||
650 | INS_ZP; | ||
651 | break; | ||
652 | case 0xef: /* INS abcd [unofficial] */ | ||
653 | ABSOLUTE; | ||
654 | INS; | ||
655 | break; | ||
656 | case 0xf3: /* INS (ab),y [unofficial] */ | ||
657 | INDIRECT_Y; | ||
658 | INS; | ||
659 | break; | ||
660 | case 0xf7: /* INS ab,x [unofficial] */ | ||
661 | ZPAGE_X; | ||
662 | INS_ZP; | ||
663 | break; | ||
664 | case 0xfb: /* INS abcd,y [unofficial] */ | ||
665 | ABSOLUTE_Y; | ||
666 | INS; | ||
667 | break; | ||
668 | case 0xff: /* INS abcd,x [unofficial] */ | ||
669 | ABSOLUTE_X; | ||
670 | INS; | ||
671 | break; | ||
672 | #endif /* ACPU_NO_UNOFFICIAL */ | ||
673 | case 0x05: /* ORA ab */ | ||
674 | ZPAGE; | ||
675 | ORA_ZP; | ||
676 | break; | ||
677 | case 0x06: /* ASL ab */ | ||
678 | ZPAGE; | ||
679 | ASL_ZP; | ||
680 | break; | ||
681 | case 0x08: /* PHP */ | ||
682 | PHPB1; | ||
683 | break; | ||
684 | case 0x09: /* ORA #ab */ | ||
685 | nz = a |= FETCH; | ||
686 | break; | ||
687 | case 0x0a: /* ASL */ | ||
688 | c = a >> 7; | ||
689 | nz = a = (a << 1) & 0xff; | ||
690 | break; | ||
691 | case 0x0d: /* ORA abcd */ | ||
692 | ABSOLUTE; | ||
693 | ORA; | ||
694 | break; | ||
695 | case 0x0e: /* ASL abcd */ | ||
696 | ABSOLUTE; | ||
697 | ASL; | ||
698 | break; | ||
699 | case 0x10: /* BPL */ | ||
700 | BRANCH(nz < 0x80); | ||
701 | case 0x11: /* ORA (ab),y */ | ||
702 | INDIRECT_Y; | ||
703 | NCYCLES_Y; | ||
704 | ORA; | ||
705 | break; | ||
706 | case 0x15: /* ORA ab,x */ | ||
707 | ZPAGE_X; | ||
708 | ORA_ZP; | ||
709 | break; | ||
710 | case 0x16: /* ASL ab,x */ | ||
711 | ZPAGE_X; | ||
712 | ASL_ZP; | ||
713 | break; | ||
714 | case 0x18: /* CLC */ | ||
715 | c = 0; | ||
716 | break; | ||
717 | case 0x19: /* ORA abcd,y */ | ||
718 | ABSOLUTE_Y; | ||
719 | NCYCLES_Y; | ||
720 | ORA; | ||
721 | break; | ||
722 | case 0x1d: /* ORA abcd,x */ | ||
723 | ABSOLUTE_X; | ||
724 | NCYCLES_X; | ||
725 | ORA; | ||
726 | break; | ||
727 | case 0x1e: /* ASL abcd,x */ | ||
728 | ABSOLUTE_X; | ||
729 | ASL; | ||
730 | break; | ||
731 | case 0x20: /* JSR abcd */ | ||
732 | addr = FETCH; | ||
733 | PHPC; | ||
734 | pc = addr + (PEEK << 8); | ||
735 | break; | ||
736 | case 0x21: /* AND (ab,x) */ | ||
737 | INDIRECT_X; | ||
738 | AND; | ||
739 | break; | ||
740 | case 0x24: /* BIT ab */ | ||
741 | ZPAGE; | ||
742 | nz = dGetByte(addr); | ||
743 | vdi = (vdi & (D_FLAG | I_FLAG)) + (nz & V_FLAG); | ||
744 | nz = ((nz & 0x80) << 1) + (nz & a); | ||
745 | break; | ||
746 | case 0x25: /* AND ab */ | ||
747 | ZPAGE; | ||
748 | AND_ZP; | ||
749 | break; | ||
750 | case 0x26: /* ROL ab */ | ||
751 | ZPAGE; | ||
752 | ROL_ZP; | ||
753 | break; | ||
754 | case 0x28: /* PLP */ | ||
755 | PLP; | ||
756 | CHECK_IRQ; | ||
757 | break; | ||
758 | case 0x29: /* AND #ab */ | ||
759 | nz = a &= FETCH; | ||
760 | break; | ||
761 | case 0x2a: /* ROL */ | ||
762 | a = (a << 1) + c; | ||
763 | c = a >> 8; | ||
764 | nz = a &= 0xff; | ||
765 | break; | ||
766 | case 0x2c: /* BIT abcd */ | ||
767 | ABSOLUTE; | ||
768 | nz = GetByte(addr); | ||
769 | vdi = (vdi & (D_FLAG | I_FLAG)) + (nz & V_FLAG); | ||
770 | nz = ((nz & 0x80) << 1) + (nz & a); | ||
771 | break; | ||
772 | case 0x2d: /* AND abcd */ | ||
773 | ABSOLUTE; | ||
774 | AND; | ||
775 | break; | ||
776 | case 0x2e: /* ROL abcd */ | ||
777 | ABSOLUTE; | ||
778 | ROL; | ||
779 | break; | ||
780 | case 0x30: /* BMI */ | ||
781 | BRANCH(nz >= 0x80); | ||
782 | case 0x31: /* AND (ab),y */ | ||
783 | INDIRECT_Y; | ||
784 | NCYCLES_Y; | ||
785 | AND; | ||
786 | break; | ||
787 | case 0x35: /* AND ab,x */ | ||
788 | ZPAGE_X; | ||
789 | AND_ZP; | ||
790 | break; | ||
791 | case 0x36: /* ROL ab,x */ | ||
792 | ZPAGE_X; | ||
793 | ROL_ZP; | ||
794 | break; | ||
795 | case 0x38: /* SEC */ | ||
796 | c = 1; | ||
797 | break; | ||
798 | case 0x39: /* AND abcd,y */ | ||
799 | ABSOLUTE_Y; | ||
800 | NCYCLES_Y; | ||
801 | AND; | ||
802 | break; | ||
803 | case 0x3d: /* AND abcd,x */ | ||
804 | ABSOLUTE_X; | ||
805 | NCYCLES_X; | ||
806 | AND; | ||
807 | break; | ||
808 | case 0x3e: /* ROL abcd,x */ | ||
809 | ABSOLUTE_X; | ||
810 | ROL; | ||
811 | break; | ||
812 | case 0x40: /* RTI */ | ||
813 | PLP; | ||
814 | PL(pc); | ||
815 | PL(addr); | ||
816 | pc += addr << 8; | ||
817 | CHECK_IRQ; | ||
818 | break; | ||
819 | case 0x41: /* EOR (ab,x) */ | ||
820 | INDIRECT_X; | ||
821 | EOR; | ||
822 | break; | ||
823 | case 0x45: /* EOR ab */ | ||
824 | ZPAGE; | ||
825 | EOR_ZP; | ||
826 | break; | ||
827 | case 0x46: /* LSR ab */ | ||
828 | ZPAGE; | ||
829 | LSR_ZP; | ||
830 | break; | ||
831 | case 0x48: /* PHA */ | ||
832 | PH(a); | ||
833 | break; | ||
834 | case 0x49: /* EOR #ab */ | ||
835 | nz = a ^= FETCH; | ||
836 | break; | ||
837 | case 0x4a: /* LSR */ | ||
838 | c = a & 1; | ||
839 | nz = a >>= 1; | ||
840 | break; | ||
841 | case 0x4c: /* JMP abcd */ | ||
842 | addr = FETCH; | ||
843 | pc = addr + (PEEK << 8); | ||
844 | break; | ||
845 | case 0x4d: /* EOR abcd */ | ||
846 | ABSOLUTE; | ||
847 | EOR; | ||
848 | break; | ||
849 | case 0x4e: /* LSR abcd */ | ||
850 | ABSOLUTE; | ||
851 | LSR; | ||
852 | break; | ||
853 | case 0x50: /* BVC */ | ||
854 | BRANCH((vdi & V_FLAG) == 0); | ||
855 | case 0x51: /* EOR (ab),y */ | ||
856 | INDIRECT_Y; | ||
857 | NCYCLES_Y; | ||
858 | EOR; | ||
859 | break; | ||
860 | case 0x55: /* EOR ab,x */ | ||
861 | ZPAGE_X; | ||
862 | EOR_ZP; | ||
863 | break; | ||
864 | case 0x56: /* LSR ab,x */ | ||
865 | ZPAGE_X; | ||
866 | LSR_ZP; | ||
867 | break; | ||
868 | case 0x58: /* CLI */ | ||
869 | vdi &= V_FLAG | D_FLAG; | ||
870 | CHECK_IRQ; | ||
871 | break; | ||
872 | case 0x59: /* EOR abcd,y */ | ||
873 | ABSOLUTE_Y; | ||
874 | NCYCLES_Y; | ||
875 | EOR; | ||
876 | break; | ||
877 | case 0x5d: /* EOR abcd,x */ | ||
878 | ABSOLUTE_X; | ||
879 | NCYCLES_X; | ||
880 | EOR; | ||
881 | break; | ||
882 | case 0x5e: /* LSR abcd,x */ | ||
883 | ABSOLUTE_X; | ||
884 | LSR; | ||
885 | break; | ||
886 | case 0x60: /* RTS */ | ||
887 | PL(pc); | ||
888 | PL(addr); | ||
889 | pc += (addr << 8) + 1; | ||
890 | break; | ||
891 | case 0x61: /* ADC (ab,x) */ | ||
892 | INDIRECT_X; | ||
893 | ADC; | ||
894 | break; | ||
895 | case 0x65: /* ADC ab */ | ||
896 | ZPAGE; | ||
897 | ADC_ZP; | ||
898 | break; | ||
899 | case 0x66: /* ROR ab */ | ||
900 | ZPAGE; | ||
901 | ROR_ZP; | ||
902 | break; | ||
903 | case 0x68: /* PLA */ | ||
904 | PL(a); | ||
905 | nz = a; | ||
906 | break; | ||
907 | case 0x69: /* ADC #ab */ | ||
908 | data = FETCH; | ||
909 | DO_ADC; | ||
910 | break; | ||
911 | case 0x6a: /* ROR */ | ||
912 | nz = (c << 7) + (a >> 1); | ||
913 | c = a & 1; | ||
914 | a = nz; | ||
915 | break; | ||
916 | case 0x6c: /* JMP (abcd) */ | ||
917 | ABSOLUTE; | ||
918 | if ((addr & 0xff) == 0xff) | ||
919 | pc = (dGetByte(addr - 0xff) << 8) + dGetByte(addr); | ||
920 | else | ||
921 | pc = dGetWord(addr); | ||
922 | break; | ||
923 | case 0x6d: /* ADC abcd */ | ||
924 | ABSOLUTE; | ||
925 | ADC; | ||
926 | break; | ||
927 | case 0x6e: /* ROR abcd */ | ||
928 | ABSOLUTE; | ||
929 | ROR; | ||
930 | break; | ||
931 | case 0x70: /* BVS */ | ||
932 | BRANCH((vdi & V_FLAG) != 0); | ||
933 | case 0x71: /* ADC (ab),y */ | ||
934 | INDIRECT_Y; | ||
935 | NCYCLES_Y; | ||
936 | ADC; | ||
937 | break; | ||
938 | case 0x75: /* ADC ab,x */ | ||
939 | ZPAGE_X; | ||
940 | ADC_ZP; | ||
941 | break; | ||
942 | case 0x76: /* ROR ab,x */ | ||
943 | ZPAGE_X; | ||
944 | ROR_ZP; | ||
945 | break; | ||
946 | case 0x78: /* SEI */ | ||
947 | vdi |= I_FLAG; | ||
948 | break; | ||
949 | case 0x79: /* ADC abcd,y */ | ||
950 | ABSOLUTE_Y; | ||
951 | NCYCLES_Y; | ||
952 | ADC; | ||
953 | break; | ||
954 | case 0x7d: /* ADC abcd,x */ | ||
955 | ABSOLUTE_X; | ||
956 | NCYCLES_X; | ||
957 | ADC; | ||
958 | break; | ||
959 | case 0x7e: /* ROR abcd,x */ | ||
960 | ABSOLUTE_X; | ||
961 | ROR; | ||
962 | break; | ||
963 | case 0x81: /* STA (ab,x) */ | ||
964 | INDIRECT_X; | ||
965 | STA; | ||
966 | break; | ||
967 | case 0x84: /* STY ab */ | ||
968 | ZPAGE; | ||
969 | STY_ZP; | ||
970 | break; | ||
971 | case 0x85: /* STA ab */ | ||
972 | ZPAGE; | ||
973 | STA_ZP; | ||
974 | break; | ||
975 | case 0x86: /* STX ab */ | ||
976 | ZPAGE; | ||
977 | STX_ZP; | ||
978 | break; | ||
979 | case 0x88: /* DEY */ | ||
980 | nz = y = (y - 1) & 0xff; | ||
981 | break; | ||
982 | case 0x8a: /* TXA */ | ||
983 | nz = a = x; | ||
984 | break; | ||
985 | case 0x8c: /* STY abcd */ | ||
986 | ABSOLUTE; | ||
987 | STY; | ||
988 | break; | ||
989 | case 0x8d: /* STA abcd */ | ||
990 | ABSOLUTE; | ||
991 | STA; | ||
992 | break; | ||
993 | case 0x8e: /* STX abcd */ | ||
994 | ABSOLUTE; | ||
995 | STX; | ||
996 | break; | ||
997 | case 0x90: /* BCC */ | ||
998 | BRANCH(c == 0); | ||
999 | case 0x91: /* STA (ab),y */ | ||
1000 | INDIRECT_Y; | ||
1001 | STA; | ||
1002 | break; | ||
1003 | case 0x94: /* STY ab,x */ | ||
1004 | ZPAGE_X; | ||
1005 | STY_ZP; | ||
1006 | break; | ||
1007 | case 0x95: /* STA ab,x */ | ||
1008 | ZPAGE_X; | ||
1009 | STA_ZP; | ||
1010 | break; | ||
1011 | case 0x96: /* STX ab,y */ | ||
1012 | ZPAGE_Y; | ||
1013 | STX_ZP; | ||
1014 | break; | ||
1015 | case 0x98: /* TYA */ | ||
1016 | nz = a = y; | ||
1017 | break; | ||
1018 | case 0x99: /* STA abcd,y */ | ||
1019 | ABSOLUTE_Y; | ||
1020 | STA; | ||
1021 | break; | ||
1022 | case 0x9a: /* TXS */ | ||
1023 | s = x; | ||
1024 | break; | ||
1025 | case 0x9d: /* STA abcd,x */ | ||
1026 | ABSOLUTE_X; | ||
1027 | STA; | ||
1028 | break; | ||
1029 | case 0xa0: /* LDY #ab */ | ||
1030 | nz = y = FETCH; | ||
1031 | break; | ||
1032 | case 0xa1: /* LDA (ab,x) */ | ||
1033 | INDIRECT_X; | ||
1034 | LDA; | ||
1035 | break; | ||
1036 | case 0xa2: /* LDX #ab */ | ||
1037 | nz = x = FETCH; | ||
1038 | break; | ||
1039 | case 0xa4: /* LDY ab */ | ||
1040 | ZPAGE; | ||
1041 | LDY_ZP; | ||
1042 | break; | ||
1043 | case 0xa5: /* LDA ab */ | ||
1044 | ZPAGE; | ||
1045 | LDA_ZP; | ||
1046 | break; | ||
1047 | case 0xa6: /* LDX ab */ | ||
1048 | ZPAGE; | ||
1049 | LDX_ZP; | ||
1050 | break; | ||
1051 | case 0xa8: /* TAY */ | ||
1052 | nz = y = a; | ||
1053 | break; | ||
1054 | case 0xa9: /* LDA #ab */ | ||
1055 | nz = a = FETCH; | ||
1056 | break; | ||
1057 | case 0xaa: /* TAX */ | ||
1058 | nz = x = a; | ||
1059 | break; | ||
1060 | case 0xac: /* LDY abcd */ | ||
1061 | ABSOLUTE; | ||
1062 | LDY; | ||
1063 | break; | ||
1064 | case 0xad: /* LDA abcd */ | ||
1065 | ABSOLUTE; | ||
1066 | LDA; | ||
1067 | break; | ||
1068 | case 0xae: /* LDX abcd */ | ||
1069 | ABSOLUTE; | ||
1070 | LDX; | ||
1071 | break; | ||
1072 | case 0xb0: /* BCS */ | ||
1073 | BRANCH(c != 0); | ||
1074 | case 0xb1: /* LDA (ab),y */ | ||
1075 | INDIRECT_Y; | ||
1076 | NCYCLES_Y; | ||
1077 | LDA; | ||
1078 | break; | ||
1079 | case 0xb4: /* LDY ab,x */ | ||
1080 | ZPAGE_X; | ||
1081 | LDY_ZP; | ||
1082 | break; | ||
1083 | case 0xb5: /* LDA ab,x */ | ||
1084 | ZPAGE_X; | ||
1085 | LDA_ZP; | ||
1086 | break; | ||
1087 | case 0xb6: /* LDX ab,y */ | ||
1088 | ZPAGE_Y; | ||
1089 | LDX_ZP; | ||
1090 | break; | ||
1091 | case 0xb8: /* CLV */ | ||
1092 | vdi &= D_FLAG | I_FLAG; | ||
1093 | break; | ||
1094 | case 0xb9: /* LDA abcd,y */ | ||
1095 | ABSOLUTE_Y; | ||
1096 | NCYCLES_Y; | ||
1097 | LDA; | ||
1098 | break; | ||
1099 | case 0xba: /* TSX */ | ||
1100 | nz = x = s; | ||
1101 | break; | ||
1102 | case 0xbc: /* LDY abcd,x */ | ||
1103 | ABSOLUTE_X; | ||
1104 | NCYCLES_X; | ||
1105 | LDY; | ||
1106 | break; | ||
1107 | case 0xbd: /* LDA abcd,x */ | ||
1108 | ABSOLUTE_X; | ||
1109 | NCYCLES_X; | ||
1110 | LDA; | ||
1111 | break; | ||
1112 | case 0xbe: /* LDX abcd,y */ | ||
1113 | ABSOLUTE_Y; | ||
1114 | NCYCLES_Y; | ||
1115 | LDX; | ||
1116 | break; | ||
1117 | case 0xc0: /* CPY #ab */ | ||
1118 | nz = FETCH; | ||
1119 | c = (y >= nz) ? 1 : 0; | ||
1120 | nz = (y - nz) & 0xff; | ||
1121 | break; | ||
1122 | case 0xc1: /* CMP (ab,x) */ | ||
1123 | INDIRECT_X; | ||
1124 | CMP; | ||
1125 | break; | ||
1126 | case 0xc4: /* CPY ab */ | ||
1127 | ZPAGE; | ||
1128 | CPY_ZP; | ||
1129 | break; | ||
1130 | case 0xc5: /* CMP ab */ | ||
1131 | ZPAGE; | ||
1132 | CMP_ZP; | ||
1133 | break; | ||
1134 | case 0xc6: /* DEC ab */ | ||
1135 | ZPAGE; | ||
1136 | DEC_ZP; | ||
1137 | break; | ||
1138 | case 0xc8: /* INY */ | ||
1139 | nz = y = (y + 1) & 0xff; | ||
1140 | break; | ||
1141 | case 0xc9: /* CMP #ab */ | ||
1142 | nz = FETCH; | ||
1143 | c = (a >= nz) ? 1 : 0; | ||
1144 | nz = (a - nz) & 0xff; | ||
1145 | break; | ||
1146 | case 0xca: /* DEX */ | ||
1147 | nz = x = (x - 1) & 0xff; | ||
1148 | break; | ||
1149 | case 0xcc: /* CPY abcd */ | ||
1150 | ABSOLUTE; | ||
1151 | CPY; | ||
1152 | break; | ||
1153 | case 0xcd: /* CMP abcd */ | ||
1154 | ABSOLUTE; | ||
1155 | CMP; | ||
1156 | break; | ||
1157 | case 0xce: /* DEC abcd */ | ||
1158 | ABSOLUTE; | ||
1159 | DEC; | ||
1160 | break; | ||
1161 | case 0xd0: /* BNE */ | ||
1162 | BRANCH((nz & 0xff) != 0); | ||
1163 | case 0xd1: /* CMP (ab),y */ | ||
1164 | INDIRECT_Y; | ||
1165 | NCYCLES_Y; | ||
1166 | CMP; | ||
1167 | break; | ||
1168 | case 0xd5: /* CMP ab,x */ | ||
1169 | ZPAGE_X; | ||
1170 | CMP_ZP; | ||
1171 | break; | ||
1172 | case 0xd6: /* DEC ab,x */ | ||
1173 | ZPAGE_X; | ||
1174 | DEC_ZP; | ||
1175 | break; | ||
1176 | case 0xd8: /* CLD */ | ||
1177 | vdi &= V_FLAG | I_FLAG; | ||
1178 | break; | ||
1179 | case 0xd9: /* CMP abcd,y */ | ||
1180 | ABSOLUTE_Y; | ||
1181 | NCYCLES_Y; | ||
1182 | CMP; | ||
1183 | break; | ||
1184 | case 0xdd: /* CMP abcd,x */ | ||
1185 | ABSOLUTE_X; | ||
1186 | NCYCLES_X; | ||
1187 | CMP; | ||
1188 | break; | ||
1189 | case 0xde: /* DEC abcd,x */ | ||
1190 | ABSOLUTE_X; | ||
1191 | DEC; | ||
1192 | break; | ||
1193 | case 0xe0: /* CPX #ab */ | ||
1194 | nz = FETCH; | ||
1195 | c = (x >= nz) ? 1 : 0; | ||
1196 | nz = (x - nz) & 0xff; | ||
1197 | break; | ||
1198 | case 0xe1: /* SBC (ab,x) */ | ||
1199 | INDIRECT_X; | ||
1200 | SBC; | ||
1201 | break; | ||
1202 | case 0xe4: /* CPX ab */ | ||
1203 | ZPAGE; | ||
1204 | CPX_ZP; | ||
1205 | break; | ||
1206 | case 0xe5: /* SBC ab */ | ||
1207 | ZPAGE; | ||
1208 | SBC_ZP; | ||
1209 | break; | ||
1210 | case 0xe6: /* INC ab */ | ||
1211 | ZPAGE; | ||
1212 | INC_ZP; | ||
1213 | break; | ||
1214 | case 0xe8: /* INX */ | ||
1215 | nz = x = (x + 1) & 0xff; | ||
1216 | break; | ||
1217 | case 0xe9: /* SBC #ab */ | ||
1218 | case 0xeb: /* SBC #ab [unofficial] */ | ||
1219 | data = FETCH; | ||
1220 | DO_SBC; | ||
1221 | break; | ||
1222 | case 0xea: /* NOP */ | ||
1223 | case 0x1a: /* NOP [unofficial] */ | ||
1224 | case 0x3a: | ||
1225 | case 0x5a: | ||
1226 | case 0x7a: | ||
1227 | case 0xda: | ||
1228 | case 0xfa: | ||
1229 | break; | ||
1230 | case 0xec: /* CPX abcd */ | ||
1231 | ABSOLUTE; | ||
1232 | CPX; | ||
1233 | break; | ||
1234 | case 0xed: /* SBC abcd */ | ||
1235 | ABSOLUTE; | ||
1236 | SBC; | ||
1237 | break; | ||
1238 | case 0xee: /* INC abcd */ | ||
1239 | ABSOLUTE; | ||
1240 | INC; | ||
1241 | break; | ||
1242 | case 0xf0: /* BEQ */ | ||
1243 | BRANCH((nz & 0xff) == 0); | ||
1244 | case 0xf1: /* SBC (ab),y */ | ||
1245 | INDIRECT_Y; | ||
1246 | NCYCLES_Y; | ||
1247 | SBC; | ||
1248 | break; | ||
1249 | case 0xf5: /* SBC ab,x */ | ||
1250 | ZPAGE_X; | ||
1251 | SBC_ZP; | ||
1252 | break; | ||
1253 | case 0xf6: /* INC ab,x */ | ||
1254 | ZPAGE_X; | ||
1255 | INC_ZP; | ||
1256 | break; | ||
1257 | case 0xf8: /* SED */ | ||
1258 | vdi |= D_FLAG; | ||
1259 | break; | ||
1260 | case 0xf9: /* SBC abcd,y */ | ||
1261 | ABSOLUTE_Y; | ||
1262 | NCYCLES_Y; | ||
1263 | SBC; | ||
1264 | break; | ||
1265 | case 0xfd: /* SBC abcd,x */ | ||
1266 | ABSOLUTE_X; | ||
1267 | NCYCLES_X; | ||
1268 | SBC; | ||
1269 | break; | ||
1270 | case 0xfe: /* INC abcd,x */ | ||
1271 | ABSOLUTE_X; | ||
1272 | INC; | ||
1273 | break; | ||
1274 | } | ||
1275 | } | ||
1276 | ast _ cpu_pc = pc; | ||
1277 | ast _ cpu_nz = nz; | ||
1278 | ast _ cpu_a = a; | ||
1279 | ast _ cpu_x = x; | ||
1280 | ast _ cpu_y = y; | ||
1281 | ast _ cpu_c = c; | ||
1282 | ast _ cpu_s = s; | ||
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; | ||
1291 | } | ||