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