1 |
/* |
2 |
* CPU_emulcycle.h - SC 6510/6502 emulation core (body of |
3 |
* EmulateCycle() function, the same for |
4 |
* both 6510 and 6502) |
5 |
* |
6 |
* Frodo (C) 1994-1997,2002-2004 Christian Bauer |
7 |
* |
8 |
* This program is free software; you can redistribute it and/or modify |
9 |
* it under the terms of the GNU General Public License as published by |
10 |
* the Free Software Foundation; either version 2 of the License, or |
11 |
* (at your option) any later version. |
12 |
* |
13 |
* This program is distributed in the hope that it will be useful, |
14 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 |
* GNU General Public License for more details. |
17 |
* |
18 |
* You should have received a copy of the GNU General Public License |
19 |
* along with this program; if not, write to the Free Software |
20 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
21 |
*/ |
22 |
|
23 |
|
24 |
/* |
25 |
* Stack macros |
26 |
*/ |
27 |
|
28 |
// Pop processor flags from the stack |
29 |
#define pop_flags() \ |
30 |
read_to(sp | 0x100, data); \ |
31 |
n_flag = data; \ |
32 |
v_flag = data & 0x40; \ |
33 |
d_flag = data & 0x08; \ |
34 |
i_flag = data & 0x04; \ |
35 |
z_flag = !(data & 0x02); \ |
36 |
c_flag = data & 0x01; |
37 |
|
38 |
// Push processor flags onto the stack |
39 |
#define push_flags(b_flag) \ |
40 |
data = 0x20 | (n_flag & 0x80); \ |
41 |
if (v_flag) data |= 0x40; \ |
42 |
if (b_flag) data |= 0x10; \ |
43 |
if (d_flag) data |= 0x08; \ |
44 |
if (i_flag) data |= 0x04; \ |
45 |
if (!z_flag) data |= 0x02; \ |
46 |
if (c_flag) data |= 0x01; \ |
47 |
write_byte(sp-- | 0x100, data); |
48 |
|
49 |
|
50 |
/* |
51 |
* Other macros |
52 |
*/ |
53 |
|
54 |
// Branch (cycle 1) |
55 |
#define Branch(flag) \ |
56 |
read_to(pc++, data); \ |
57 |
if (flag) { \ |
58 |
ar = pc + (int8)data; \ |
59 |
if ((ar >> 8) != (pc >> 8)) { \ |
60 |
if (data & 0x80) \ |
61 |
state = O_BRANCH_BP; \ |
62 |
else \ |
63 |
state = O_BRANCH_FP; \ |
64 |
} else \ |
65 |
state = O_BRANCH_NP; \ |
66 |
} else \ |
67 |
state = 0; \ |
68 |
break; |
69 |
|
70 |
// Set N and Z flags according to byte |
71 |
#define set_nz(x) (z_flag = n_flag = (x)) |
72 |
|
73 |
// Address fetch of RMW instruction done, now read and write operand |
74 |
#define DoRMW state = RMW_DO_IT; break; |
75 |
|
76 |
// Operand fetch done, now execute opcode |
77 |
#define Execute state = OpTab[op]; break; |
78 |
|
79 |
// Last cycle of opcode |
80 |
#define Last state = 0; break; |
81 |
|
82 |
|
83 |
/* |
84 |
* EmulCycle() function |
85 |
*/ |
86 |
|
87 |
switch (state) { |
88 |
|
89 |
|
90 |
// Opcode fetch (cycle 0) |
91 |
case 0: |
92 |
read_to(pc++, op); |
93 |
state = ModeTab[op]; |
94 |
break; |
95 |
|
96 |
|
97 |
// IRQ |
98 |
case 0x0008: |
99 |
read_idle(pc); |
100 |
state = 0x0009; |
101 |
break; |
102 |
case 0x0009: |
103 |
read_idle(pc); |
104 |
state = 0x000a; |
105 |
break; |
106 |
case 0x000a: |
107 |
write_byte(sp-- | 0x100, pc >> 8); |
108 |
state = 0x000b; |
109 |
break; |
110 |
case 0x000b: |
111 |
write_byte(sp-- | 0x100, pc); |
112 |
state = 0x000c; |
113 |
break; |
114 |
case 0x000c: |
115 |
push_flags(false); |
116 |
i_flag = true; |
117 |
state = 0x000d; |
118 |
break; |
119 |
case 0x000d: |
120 |
read_to(0xfffe, pc); |
121 |
state = 0x000e; |
122 |
break; |
123 |
case 0x000e: |
124 |
read_to(0xffff, data); |
125 |
pc |= data << 8; |
126 |
Last; |
127 |
|
128 |
|
129 |
// NMI |
130 |
case 0x0010: |
131 |
read_idle(pc); |
132 |
state = 0x0011; |
133 |
break; |
134 |
case 0x0011: |
135 |
read_idle(pc); |
136 |
state = 0x0012; |
137 |
break; |
138 |
case 0x0012: |
139 |
write_byte(sp-- | 0x100, pc >> 8); |
140 |
state = 0x0013; |
141 |
break; |
142 |
case 0x0013: |
143 |
write_byte(sp-- | 0x100, pc); |
144 |
state = 0x0014; |
145 |
break; |
146 |
case 0x0014: |
147 |
push_flags(false); |
148 |
i_flag = true; |
149 |
state = 0x0015; |
150 |
break; |
151 |
case 0x0015: |
152 |
read_to(0xfffa, pc); |
153 |
state = 0x0016; |
154 |
break; |
155 |
case 0x0016: |
156 |
read_to(0xfffb, data); |
157 |
pc |= data << 8; |
158 |
Last; |
159 |
|
160 |
|
161 |
// Addressing modes: Fetch effective address, no extra cycles (-> ar) |
162 |
case A_ZERO: |
163 |
read_to(pc++, ar); |
164 |
Execute; |
165 |
|
166 |
case A_ZEROX: |
167 |
read_to(pc++, ar); |
168 |
state = A_ZEROX1; |
169 |
break; |
170 |
case A_ZEROX1: |
171 |
read_idle(ar); |
172 |
ar = (ar + x) & 0xff; |
173 |
Execute; |
174 |
|
175 |
case A_ZEROY: |
176 |
read_to(pc++, ar); |
177 |
state = A_ZEROY1; |
178 |
break; |
179 |
case A_ZEROY1: |
180 |
read_idle(ar); |
181 |
ar = (ar + y) & 0xff; |
182 |
Execute; |
183 |
|
184 |
case A_ABS: |
185 |
read_to(pc++, ar); |
186 |
state = A_ABS1; |
187 |
break; |
188 |
case A_ABS1: |
189 |
read_to(pc++, data); |
190 |
ar = ar | (data << 8); |
191 |
Execute; |
192 |
|
193 |
case A_ABSX: |
194 |
read_to(pc++, ar); |
195 |
state = A_ABSX1; |
196 |
break; |
197 |
case A_ABSX1: |
198 |
read_to(pc++, ar2); // Note: Some undocumented opcodes rely on the value of ar2 |
199 |
if (ar+x < 0x100) |
200 |
state = A_ABSX2; |
201 |
else |
202 |
state = A_ABSX3; |
203 |
ar = (ar + x) & 0xff | (ar2 << 8); |
204 |
break; |
205 |
case A_ABSX2: // No page crossed |
206 |
read_idle(ar); |
207 |
Execute; |
208 |
case A_ABSX3: // Page crossed |
209 |
read_idle(ar); |
210 |
ar += 0x100; |
211 |
Execute; |
212 |
|
213 |
case A_ABSY: |
214 |
read_to(pc++, ar); |
215 |
state = A_ABSY1; |
216 |
break; |
217 |
case A_ABSY1: |
218 |
read_to(pc++, ar2); // Note: Some undocumented opcodes rely on the value of ar2 |
219 |
if (ar+y < 0x100) |
220 |
state = A_ABSY2; |
221 |
else |
222 |
state = A_ABSY3; |
223 |
ar = (ar + y) & 0xff | (ar2 << 8); |
224 |
break; |
225 |
case A_ABSY2: // No page crossed |
226 |
read_idle(ar); |
227 |
Execute; |
228 |
case A_ABSY3: // Page crossed |
229 |
read_idle(ar); |
230 |
ar += 0x100; |
231 |
Execute; |
232 |
|
233 |
case A_INDX: |
234 |
read_to(pc++, ar2); |
235 |
state = A_INDX1; |
236 |
break; |
237 |
case A_INDX1: |
238 |
read_idle(ar2); |
239 |
ar2 = (ar2 + x) & 0xff; |
240 |
state = A_INDX2; |
241 |
break; |
242 |
case A_INDX2: |
243 |
read_to(ar2, ar); |
244 |
state = A_INDX3; |
245 |
break; |
246 |
case A_INDX3: |
247 |
read_to((ar2 + 1) & 0xff, data); |
248 |
ar = ar | (data << 8); |
249 |
Execute; |
250 |
|
251 |
case A_INDY: |
252 |
read_to(pc++, ar2); |
253 |
state = A_INDY1; |
254 |
break; |
255 |
case A_INDY1: |
256 |
read_to(ar2, ar); |
257 |
state = A_INDY2; |
258 |
break; |
259 |
case A_INDY2: |
260 |
read_to((ar2 + 1) & 0xff, ar2); // Note: Some undocumented opcodes rely on the value of ar2 |
261 |
if (ar+y < 0x100) |
262 |
state = A_INDY3; |
263 |
else |
264 |
state = A_INDY4; |
265 |
ar = (ar + y) & 0xff | (ar2 << 8); |
266 |
break; |
267 |
case A_INDY3: // No page crossed |
268 |
read_idle(ar); |
269 |
Execute; |
270 |
case A_INDY4: // Page crossed |
271 |
read_idle(ar); |
272 |
ar += 0x100; |
273 |
Execute; |
274 |
|
275 |
|
276 |
// Addressing modes: Fetch effective address, extra cycle on page crossing (-> ar) |
277 |
case AE_ABSX: |
278 |
read_to(pc++, ar); |
279 |
state = AE_ABSX1; |
280 |
break; |
281 |
case AE_ABSX1: |
282 |
read_to(pc++, data); |
283 |
if (ar+x < 0x100) { |
284 |
ar = (ar + x) & 0xff | (data << 8); |
285 |
Execute; |
286 |
} else { |
287 |
ar = (ar + x) & 0xff | (data << 8); |
288 |
state = AE_ABSX2; |
289 |
} |
290 |
break; |
291 |
case AE_ABSX2: // Page crossed |
292 |
read_idle(ar); |
293 |
ar += 0x100; |
294 |
Execute; |
295 |
|
296 |
case AE_ABSY: |
297 |
read_to(pc++, ar); |
298 |
state = AE_ABSY1; |
299 |
break; |
300 |
case AE_ABSY1: |
301 |
read_to(pc++, data); |
302 |
if (ar+y < 0x100) { |
303 |
ar = (ar + y) & 0xff | (data << 8); |
304 |
Execute; |
305 |
} else { |
306 |
ar = (ar + y) & 0xff | (data << 8); |
307 |
state = AE_ABSY2; |
308 |
} |
309 |
break; |
310 |
case AE_ABSY2: // Page crossed |
311 |
read_idle(ar); |
312 |
ar += 0x100; |
313 |
Execute; |
314 |
|
315 |
case AE_INDY: |
316 |
read_to(pc++, ar2); |
317 |
state = AE_INDY1; |
318 |
break; |
319 |
case AE_INDY1: |
320 |
read_to(ar2, ar); |
321 |
state = AE_INDY2; |
322 |
break; |
323 |
case AE_INDY2: |
324 |
read_to((ar2 + 1) & 0xff, data); |
325 |
if (ar+y < 0x100) { |
326 |
ar = (ar + y) & 0xff | (data << 8); |
327 |
Execute; |
328 |
} else { |
329 |
ar = (ar + y) & 0xff | (data << 8); |
330 |
state = AE_INDY3; |
331 |
} |
332 |
break; |
333 |
case AE_INDY3: // Page crossed |
334 |
read_idle(ar); |
335 |
ar += 0x100; |
336 |
Execute; |
337 |
|
338 |
|
339 |
// Addressing modes: Read operand, write it back, no extra cycles (-> ar, rdbuf) |
340 |
case M_ZERO: |
341 |
read_to(pc++, ar); |
342 |
DoRMW; |
343 |
|
344 |
case M_ZEROX: |
345 |
read_to(pc++, ar); |
346 |
state = M_ZEROX1; |
347 |
break; |
348 |
case M_ZEROX1: |
349 |
read_idle(ar); |
350 |
ar = (ar + x) & 0xff; |
351 |
DoRMW; |
352 |
|
353 |
case M_ZEROY: |
354 |
read_to(pc++, ar); |
355 |
state = M_ZEROY1; |
356 |
break; |
357 |
case M_ZEROY1: |
358 |
read_idle(ar); |
359 |
ar = (ar + y) & 0xff; |
360 |
DoRMW; |
361 |
|
362 |
case M_ABS: |
363 |
read_to(pc++, ar); |
364 |
state = M_ABS1; |
365 |
break; |
366 |
case M_ABS1: |
367 |
read_to(pc++, data); |
368 |
ar = ar | (data << 8); |
369 |
DoRMW; |
370 |
|
371 |
case M_ABSX: |
372 |
read_to(pc++, ar); |
373 |
state = M_ABSX1; |
374 |
break; |
375 |
case M_ABSX1: |
376 |
read_to(pc++, data); |
377 |
if (ar+x < 0x100) |
378 |
state = M_ABSX2; |
379 |
else |
380 |
state = M_ABSX3; |
381 |
ar = (ar + x) & 0xff | (data << 8); |
382 |
break; |
383 |
case M_ABSX2: // No page crossed |
384 |
read_idle(ar); |
385 |
DoRMW; |
386 |
case M_ABSX3: // Page crossed |
387 |
read_idle(ar); |
388 |
ar += 0x100; |
389 |
DoRMW; |
390 |
|
391 |
case M_ABSY: |
392 |
read_to(pc++, ar); |
393 |
state = M_ABSY1; |
394 |
break; |
395 |
case M_ABSY1: |
396 |
read_to(pc++, data); |
397 |
if (ar+y < 0x100) |
398 |
state = M_ABSY2; |
399 |
else |
400 |
state = M_ABSY3; |
401 |
ar = (ar + y) & 0xff | (data << 8); |
402 |
break; |
403 |
case M_ABSY2: // No page crossed |
404 |
read_idle(ar); |
405 |
DoRMW; |
406 |
case M_ABSY3: // Page crossed |
407 |
read_idle(ar); |
408 |
ar += 0x100; |
409 |
DoRMW; |
410 |
|
411 |
case M_INDX: |
412 |
read_to(pc++, ar2); |
413 |
state = M_INDX1; |
414 |
break; |
415 |
case M_INDX1: |
416 |
read_idle(ar2); |
417 |
ar2 = (ar2 + x) & 0xff; |
418 |
state = M_INDX2; |
419 |
break; |
420 |
case M_INDX2: |
421 |
read_to(ar2, ar); |
422 |
state = M_INDX3; |
423 |
break; |
424 |
case M_INDX3: |
425 |
read_to((ar2 + 1) & 0xff, data); |
426 |
ar = ar | (data << 8); |
427 |
DoRMW; |
428 |
|
429 |
case M_INDY: |
430 |
read_to(pc++, ar2); |
431 |
state = M_INDY1; |
432 |
break; |
433 |
case M_INDY1: |
434 |
read_to(ar2, ar); |
435 |
state = M_INDY2; |
436 |
break; |
437 |
case M_INDY2: |
438 |
read_to((ar2 + 1) & 0xff, data); |
439 |
if (ar+y < 0x100) |
440 |
state = M_INDY3; |
441 |
else |
442 |
state = M_INDY4; |
443 |
ar = (ar + y) & 0xff | (data << 8); |
444 |
break; |
445 |
case M_INDY3: // No page crossed |
446 |
read_idle(ar); |
447 |
DoRMW; |
448 |
case M_INDY4: // Page crossed |
449 |
read_idle(ar); |
450 |
ar += 0x100; |
451 |
DoRMW; |
452 |
|
453 |
case RMW_DO_IT: |
454 |
read_to(ar, rdbuf); |
455 |
state = RMW_DO_IT1; |
456 |
break; |
457 |
case RMW_DO_IT1: |
458 |
write_byte(ar, rdbuf); |
459 |
Execute; |
460 |
|
461 |
|
462 |
// Load group |
463 |
case O_LDA: |
464 |
read_to(ar, data); |
465 |
set_nz(a = data); |
466 |
Last; |
467 |
case O_LDA_I: |
468 |
read_to(pc++, data); |
469 |
set_nz(a = data); |
470 |
Last; |
471 |
|
472 |
case O_LDX: |
473 |
read_to(ar, data); |
474 |
set_nz(x = data); |
475 |
Last; |
476 |
case O_LDX_I: |
477 |
read_to(pc++, data); |
478 |
set_nz(x = data); |
479 |
Last; |
480 |
|
481 |
case O_LDY: |
482 |
read_to(ar, data); |
483 |
set_nz(y = data); |
484 |
Last; |
485 |
case O_LDY_I: |
486 |
read_to(pc++, data); |
487 |
set_nz(y = data); |
488 |
Last; |
489 |
|
490 |
|
491 |
// Store group |
492 |
case O_STA: |
493 |
write_byte(ar, a); |
494 |
Last; |
495 |
|
496 |
case O_STX: |
497 |
write_byte(ar, x); |
498 |
Last; |
499 |
|
500 |
case O_STY: |
501 |
write_byte(ar, y); |
502 |
Last; |
503 |
|
504 |
|
505 |
// Transfer group |
506 |
case O_TAX: |
507 |
read_idle(pc); |
508 |
set_nz(x = a); |
509 |
Last; |
510 |
|
511 |
case O_TXA: |
512 |
read_idle(pc); |
513 |
set_nz(a = x); |
514 |
Last; |
515 |
|
516 |
case O_TAY: |
517 |
read_idle(pc); |
518 |
set_nz(y = a); |
519 |
Last; |
520 |
|
521 |
case O_TYA: |
522 |
read_idle(pc); |
523 |
set_nz(a = y); |
524 |
Last; |
525 |
|
526 |
case O_TSX: |
527 |
read_idle(pc); |
528 |
set_nz(x = sp); |
529 |
Last; |
530 |
|
531 |
case O_TXS: |
532 |
read_idle(pc); |
533 |
sp = x; |
534 |
Last; |
535 |
|
536 |
|
537 |
// Arithmetic group |
538 |
case O_ADC: |
539 |
read_to(ar, data); |
540 |
do_adc(data); |
541 |
Last; |
542 |
case O_ADC_I: |
543 |
read_to(pc++, data); |
544 |
do_adc(data); |
545 |
Last; |
546 |
|
547 |
case O_SBC: |
548 |
read_to(ar, data); |
549 |
do_sbc(data); |
550 |
Last; |
551 |
case O_SBC_I: |
552 |
read_to(pc++, data); |
553 |
do_sbc(data); |
554 |
Last; |
555 |
|
556 |
|
557 |
// Increment/decrement group |
558 |
case O_INX: |
559 |
read_idle(pc); |
560 |
set_nz(++x); |
561 |
Last; |
562 |
|
563 |
case O_DEX: |
564 |
read_idle(pc); |
565 |
set_nz(--x); |
566 |
Last; |
567 |
|
568 |
case O_INY: |
569 |
read_idle(pc); |
570 |
set_nz(++y); |
571 |
Last; |
572 |
|
573 |
case O_DEY: |
574 |
read_idle(pc); |
575 |
set_nz(--y); |
576 |
Last; |
577 |
|
578 |
case O_INC: |
579 |
write_byte(ar, set_nz(rdbuf + 1)); |
580 |
Last; |
581 |
|
582 |
case O_DEC: |
583 |
write_byte(ar, set_nz(rdbuf - 1)); |
584 |
Last; |
585 |
|
586 |
|
587 |
// Logic group |
588 |
case O_AND: |
589 |
read_to(ar, data); |
590 |
set_nz(a &= data); |
591 |
Last; |
592 |
case O_AND_I: |
593 |
read_to(pc++, data); |
594 |
set_nz(a &= data); |
595 |
Last; |
596 |
|
597 |
case O_ORA: |
598 |
read_to(ar, data); |
599 |
set_nz(a |= data); |
600 |
Last; |
601 |
case O_ORA_I: |
602 |
read_to(pc++, data); |
603 |
set_nz(a |= data); |
604 |
Last; |
605 |
|
606 |
case O_EOR: |
607 |
read_to(ar, data); |
608 |
set_nz(a ^= data); |
609 |
Last; |
610 |
case O_EOR_I: |
611 |
read_to(pc++, data); |
612 |
set_nz(a ^= data); |
613 |
Last; |
614 |
|
615 |
// Compare group |
616 |
case O_CMP: |
617 |
read_to(ar, data); |
618 |
set_nz(ar = a - data); |
619 |
c_flag = ar < 0x100; |
620 |
Last; |
621 |
case O_CMP_I: |
622 |
read_to(pc++, data); |
623 |
set_nz(ar = a - data); |
624 |
c_flag = ar < 0x100; |
625 |
Last; |
626 |
|
627 |
case O_CPX: |
628 |
read_to(ar, data); |
629 |
set_nz(ar = x - data); |
630 |
c_flag = ar < 0x100; |
631 |
Last; |
632 |
case O_CPX_I: |
633 |
read_to(pc++, data); |
634 |
set_nz(ar = x - data); |
635 |
c_flag = ar < 0x100; |
636 |
Last; |
637 |
|
638 |
case O_CPY: |
639 |
read_to(ar, data); |
640 |
set_nz(ar = y - data); |
641 |
c_flag = ar < 0x100; |
642 |
Last; |
643 |
case O_CPY_I: |
644 |
read_to(pc++, data); |
645 |
set_nz(ar = y - data); |
646 |
c_flag = ar < 0x100; |
647 |
Last; |
648 |
|
649 |
|
650 |
// Bit-test group |
651 |
case O_BIT: |
652 |
read_to(ar, data); |
653 |
z_flag = a & data; |
654 |
n_flag = data; |
655 |
v_flag = data & 0x40; |
656 |
Last; |
657 |
|
658 |
|
659 |
// Shift/rotate group |
660 |
case O_ASL: |
661 |
c_flag = rdbuf & 0x80; |
662 |
write_byte(ar, set_nz(rdbuf << 1)); |
663 |
Last; |
664 |
case O_ASL_A: |
665 |
read_idle(pc); |
666 |
c_flag = a & 0x80; |
667 |
set_nz(a <<= 1); |
668 |
Last; |
669 |
|
670 |
case O_LSR: |
671 |
c_flag = rdbuf & 0x01; |
672 |
write_byte(ar, set_nz(rdbuf >> 1)); |
673 |
Last; |
674 |
case O_LSR_A: |
675 |
read_idle(pc); |
676 |
c_flag = a & 0x01; |
677 |
set_nz(a >>= 1); |
678 |
Last; |
679 |
|
680 |
case O_ROL: |
681 |
write_byte(ar, set_nz(c_flag ? (rdbuf << 1) | 0x01 : rdbuf << 1)); |
682 |
c_flag = rdbuf & 0x80; |
683 |
Last; |
684 |
case O_ROL_A: |
685 |
read_idle(pc); |
686 |
data = a & 0x80; |
687 |
set_nz(a = c_flag ? (a << 1) | 0x01 : a << 1); |
688 |
c_flag = data; |
689 |
Last; |
690 |
|
691 |
case O_ROR: |
692 |
write_byte(ar, set_nz(c_flag ? (rdbuf >> 1) | 0x80 : rdbuf >> 1)); |
693 |
c_flag = rdbuf & 0x01; |
694 |
Last; |
695 |
case O_ROR_A: |
696 |
read_idle(pc); |
697 |
data = a & 0x01; |
698 |
set_nz(a = (c_flag ? (a >> 1) | 0x80 : a >> 1)); |
699 |
c_flag = data; |
700 |
Last; |
701 |
|
702 |
|
703 |
// Stack group |
704 |
case O_PHA: |
705 |
read_idle(pc); |
706 |
state = O_PHA1; |
707 |
break; |
708 |
case O_PHA1: |
709 |
write_byte(sp-- | 0x100, a); |
710 |
Last; |
711 |
|
712 |
case O_PLA: |
713 |
read_idle(pc); |
714 |
state = O_PLA1; |
715 |
break; |
716 |
case O_PLA1: |
717 |
read_idle(sp++ | 0x100); |
718 |
state = O_PLA2; |
719 |
break; |
720 |
case O_PLA2: |
721 |
read_to(sp | 0x100, data); |
722 |
set_nz(a = data); |
723 |
Last; |
724 |
|
725 |
case O_PHP: |
726 |
read_idle(pc); |
727 |
state = O_PHP1; |
728 |
break; |
729 |
case O_PHP1: |
730 |
push_flags(true); |
731 |
Last; |
732 |
|
733 |
case O_PLP: |
734 |
read_idle(pc); |
735 |
state = O_PLP1; |
736 |
break; |
737 |
case O_PLP1: |
738 |
read_idle(sp++ | 0x100); |
739 |
state = O_PLP2; |
740 |
break; |
741 |
case O_PLP2: |
742 |
pop_flags(); |
743 |
Last; |
744 |
|
745 |
|
746 |
// Jump/branch group |
747 |
case O_JMP: |
748 |
read_to(pc++, ar); |
749 |
state = O_JMP1; |
750 |
break; |
751 |
case O_JMP1: |
752 |
read_to(pc, data); |
753 |
pc = (data << 8) | ar; |
754 |
Last; |
755 |
|
756 |
case O_JMP_I: |
757 |
read_to(ar, pc); |
758 |
state = O_JMP_I1; |
759 |
break; |
760 |
case O_JMP_I1: |
761 |
read_to((ar + 1) & 0xff | ar & 0xff00, data); |
762 |
pc |= data << 8; |
763 |
Last; |
764 |
|
765 |
case O_JSR: |
766 |
read_to(pc++, ar); |
767 |
state = O_JSR1; |
768 |
break; |
769 |
case O_JSR1: |
770 |
read_idle(sp | 0x100); |
771 |
state = O_JSR2; |
772 |
break; |
773 |
case O_JSR2: |
774 |
write_byte(sp-- | 0x100, pc >> 8); |
775 |
state = O_JSR3; |
776 |
break; |
777 |
case O_JSR3: |
778 |
write_byte(sp-- | 0x100, pc); |
779 |
state = O_JSR4; |
780 |
break; |
781 |
case O_JSR4: |
782 |
read_to(pc++, data); |
783 |
pc = ar | (data << 8); |
784 |
Last; |
785 |
|
786 |
case O_RTS: |
787 |
read_idle(pc); |
788 |
state = O_RTS1; |
789 |
break; |
790 |
case O_RTS1: |
791 |
read_idle(sp++ | 0x100); |
792 |
state = O_RTS2; |
793 |
break; |
794 |
case O_RTS2: |
795 |
read_to(sp++ | 0x100, pc); |
796 |
state = O_RTS3; |
797 |
break; |
798 |
case O_RTS3: |
799 |
read_to(sp | 0x100, data); |
800 |
pc |= data << 8; |
801 |
state = O_RTS4; |
802 |
break; |
803 |
case O_RTS4: |
804 |
read_idle(pc++); |
805 |
Last; |
806 |
|
807 |
case O_RTI: |
808 |
read_idle(pc); |
809 |
state = O_RTI1; |
810 |
break; |
811 |
case O_RTI1: |
812 |
read_idle(sp++ | 0x100); |
813 |
state = O_RTI2; |
814 |
break; |
815 |
case O_RTI2: |
816 |
pop_flags(); |
817 |
sp++; |
818 |
state = O_RTI3; |
819 |
break; |
820 |
case O_RTI3: |
821 |
read_to(sp++ | 0x100, pc); |
822 |
state = O_RTI4; |
823 |
break; |
824 |
case O_RTI4: |
825 |
read_to(sp | 0x100, data); |
826 |
pc |= data << 8; |
827 |
Last; |
828 |
|
829 |
case O_BRK: |
830 |
read_idle(pc++); |
831 |
state = O_BRK1; |
832 |
break; |
833 |
case O_BRK1: |
834 |
write_byte(sp-- | 0x100, pc >> 8); |
835 |
state = O_BRK2; |
836 |
break; |
837 |
case O_BRK2: |
838 |
write_byte(sp-- | 0x100, pc); |
839 |
state = O_BRK3; |
840 |
break; |
841 |
case O_BRK3: |
842 |
push_flags(true); |
843 |
i_flag = true; |
844 |
#ifndef IS_CPU_1541 |
845 |
if (interrupt.intr[INT_NMI]) { // BRK interrupted by NMI? |
846 |
interrupt.intr[INT_NMI] = false; // Simulate an edge-triggered input |
847 |
state = 0x0015; // Jump to NMI sequence |
848 |
break; |
849 |
} |
850 |
#endif |
851 |
state = O_BRK4; |
852 |
break; |
853 |
case O_BRK4: |
854 |
#ifndef IS_CPU_1541 |
855 |
first_nmi_cycle++; // Delay NMI |
856 |
#endif |
857 |
read_to(0xfffe, pc); |
858 |
state = O_BRK5; |
859 |
break; |
860 |
case O_BRK5: |
861 |
read_to(0xffff, data); |
862 |
pc |= data << 8; |
863 |
Last; |
864 |
|
865 |
case O_BCS: |
866 |
Branch(c_flag); |
867 |
|
868 |
case O_BCC: |
869 |
Branch(!c_flag); |
870 |
|
871 |
case O_BEQ: |
872 |
Branch(!z_flag); |
873 |
|
874 |
case O_BNE: |
875 |
Branch(z_flag); |
876 |
|
877 |
case O_BVS: |
878 |
#ifndef IS_CPU_1541 |
879 |
Branch(v_flag); |
880 |
#else |
881 |
Branch((via2_pcr & 0x0e) == 0x0e ? 1 : v_flag); // GCR byte ready flag |
882 |
#endif |
883 |
|
884 |
case O_BVC: |
885 |
#ifndef IS_CPU_1541 |
886 |
Branch(!v_flag); |
887 |
#else |
888 |
Branch(!((via2_pcr & 0x0e) == 0x0e) ? 0 : v_flag); // GCR byte ready flag |
889 |
#endif |
890 |
|
891 |
case O_BMI: |
892 |
Branch(n_flag & 0x80); |
893 |
|
894 |
case O_BPL: |
895 |
Branch(!(n_flag & 0x80)); |
896 |
|
897 |
case O_BRANCH_NP: // No page crossed |
898 |
first_irq_cycle++; // Delay IRQ |
899 |
#ifndef IS_CPU_1541 |
900 |
first_nmi_cycle++; // Delay NMI |
901 |
#endif |
902 |
read_idle(pc); |
903 |
pc = ar; |
904 |
Last; |
905 |
case O_BRANCH_BP: // Page crossed, branch backwards |
906 |
read_idle(pc); |
907 |
pc = ar; |
908 |
state = O_BRANCH_BP1; |
909 |
break; |
910 |
case O_BRANCH_BP1: |
911 |
read_idle(pc + 0x100); |
912 |
Last; |
913 |
case O_BRANCH_FP: // Page crossed, branch forwards |
914 |
read_idle(pc); |
915 |
pc = ar; |
916 |
state = O_BRANCH_FP1; |
917 |
break; |
918 |
case O_BRANCH_FP1: |
919 |
read_idle(pc - 0x100); |
920 |
Last; |
921 |
|
922 |
|
923 |
// Flag group |
924 |
case O_SEC: |
925 |
read_idle(pc); |
926 |
c_flag = true; |
927 |
Last; |
928 |
|
929 |
case O_CLC: |
930 |
read_idle(pc); |
931 |
c_flag = false; |
932 |
Last; |
933 |
|
934 |
case O_SED: |
935 |
read_idle(pc); |
936 |
d_flag = true; |
937 |
Last; |
938 |
|
939 |
case O_CLD: |
940 |
read_idle(pc); |
941 |
d_flag = false; |
942 |
Last; |
943 |
|
944 |
case O_SEI: |
945 |
read_idle(pc); |
946 |
i_flag = true; |
947 |
Last; |
948 |
|
949 |
case O_CLI: |
950 |
read_idle(pc); |
951 |
i_flag = false; |
952 |
Last; |
953 |
|
954 |
case O_CLV: |
955 |
read_idle(pc); |
956 |
v_flag = false; |
957 |
Last; |
958 |
|
959 |
|
960 |
// NOP group |
961 |
case O_NOP: |
962 |
read_idle(pc); |
963 |
Last; |
964 |
|
965 |
|
966 |
/* |
967 |
* Undocumented opcodes start here |
968 |
*/ |
969 |
|
970 |
// NOP group |
971 |
case O_NOP_I: |
972 |
read_idle(pc++); |
973 |
Last; |
974 |
|
975 |
case O_NOP_A: |
976 |
read_idle(ar); |
977 |
Last; |
978 |
|
979 |
|
980 |
// Load A/X group |
981 |
case O_LAX: |
982 |
read_to(ar, data); |
983 |
set_nz(a = x = data); |
984 |
Last; |
985 |
|
986 |
|
987 |
// Store A/X group |
988 |
case O_SAX: |
989 |
write_byte(ar, a & x); |
990 |
Last; |
991 |
|
992 |
|
993 |
// ASL/ORA group |
994 |
case O_SLO: |
995 |
c_flag = rdbuf & 0x80; |
996 |
rdbuf <<= 1; |
997 |
write_byte(ar, rdbuf); |
998 |
set_nz(a |= rdbuf); |
999 |
Last; |
1000 |
|
1001 |
|
1002 |
// ROL/AND group |
1003 |
case O_RLA: |
1004 |
tmp = rdbuf & 0x80; |
1005 |
rdbuf = c_flag ? (rdbuf << 1) | 0x01 : rdbuf << 1; |
1006 |
c_flag = tmp; |
1007 |
write_byte(ar, rdbuf); |
1008 |
set_nz(a &= rdbuf); |
1009 |
Last; |
1010 |
|
1011 |
|
1012 |
// LSR/EOR group |
1013 |
case O_SRE: |
1014 |
c_flag = rdbuf & 0x01; |
1015 |
rdbuf >>= 1; |
1016 |
write_byte(ar, rdbuf); |
1017 |
set_nz(a ^= rdbuf); |
1018 |
Last; |
1019 |
|
1020 |
|
1021 |
// ROR/ADC group |
1022 |
case O_RRA: |
1023 |
tmp = rdbuf & 0x01; |
1024 |
rdbuf = c_flag ? (rdbuf >> 1) | 0x80 : rdbuf >> 1; |
1025 |
c_flag = tmp; |
1026 |
write_byte(ar, rdbuf); |
1027 |
do_adc(rdbuf); |
1028 |
Last; |
1029 |
|
1030 |
|
1031 |
// DEC/CMP group |
1032 |
case O_DCP: |
1033 |
write_byte(ar, --rdbuf); |
1034 |
set_nz(ar = a - rdbuf); |
1035 |
c_flag = ar < 0x100; |
1036 |
Last; |
1037 |
|
1038 |
|
1039 |
// INC/SBC group |
1040 |
case O_ISB: |
1041 |
write_byte(ar, ++rdbuf); |
1042 |
do_sbc(rdbuf); |
1043 |
Last; |
1044 |
|
1045 |
|
1046 |
// Complex functions |
1047 |
case O_ANC_I: |
1048 |
read_to(pc++, data); |
1049 |
set_nz(a &= data); |
1050 |
c_flag = n_flag & 0x80; |
1051 |
Last; |
1052 |
|
1053 |
case O_ASR_I: |
1054 |
read_to(pc++, data); |
1055 |
a &= data; |
1056 |
c_flag = a & 0x01; |
1057 |
set_nz(a >>= 1); |
1058 |
Last; |
1059 |
|
1060 |
case O_ARR_I: |
1061 |
read_to(pc++, data); |
1062 |
data &= a; |
1063 |
a = (c_flag ? (data >> 1) | 0x80 : data >> 1); |
1064 |
if (!d_flag) { |
1065 |
set_nz(a); |
1066 |
c_flag = a & 0x40; |
1067 |
v_flag = (a & 0x40) ^ ((a & 0x20) << 1); |
1068 |
} else { |
1069 |
n_flag = c_flag ? 0x80 : 0; |
1070 |
z_flag = a; |
1071 |
v_flag = (data ^ a) & 0x40; |
1072 |
if ((data & 0x0f) + (data & 0x01) > 5) |
1073 |
a = a & 0xf0 | (a + 6) & 0x0f; |
1074 |
if ((c_flag = ((data + (data & 0x10)) & 0x1f0) > 0x50) != 0) |
1075 |
a += 0x60; |
1076 |
} |
1077 |
Last; |
1078 |
|
1079 |
case O_ANE_I: |
1080 |
read_to(pc++, data); |
1081 |
set_nz(a = (a | 0xee) & x & data); |
1082 |
Last; |
1083 |
|
1084 |
case O_LXA_I: |
1085 |
read_to(pc++, data); |
1086 |
set_nz(a = x = (a | 0xee) & data); |
1087 |
Last; |
1088 |
|
1089 |
case O_SBX_I: |
1090 |
read_to(pc++, data); |
1091 |
set_nz(x = ar = (x & a) - data); |
1092 |
c_flag = ar < 0x100; |
1093 |
Last; |
1094 |
|
1095 |
case O_LAS: |
1096 |
read_to(ar, data); |
1097 |
set_nz(a = x = sp = data & sp); |
1098 |
Last; |
1099 |
|
1100 |
case O_SHS: // ar2 contains the high byte of the operand address |
1101 |
write_byte(ar, (ar2+1) & (sp = a & x)); |
1102 |
Last; |
1103 |
|
1104 |
case O_SHY: // ar2 contains the high byte of the operand address |
1105 |
write_byte(ar, y & (ar2+1)); |
1106 |
Last; |
1107 |
|
1108 |
case O_SHX: // ar2 contains the high byte of the operand address |
1109 |
write_byte(ar, x & (ar2+1)); |
1110 |
Last; |
1111 |
|
1112 |
case O_SHA: // ar2 contains the high byte of the operand address |
1113 |
write_byte(ar, a & x & (ar2+1)); |
1114 |
Last; |