yaze 0.2.0
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
cpu.cc
Go to the documentation of this file.
1#include "cpu.h"
2
3#include <cstdint>
4#include <iomanip>
5#include <iostream>
6#include <sstream>
7#include <vector>
8
10
11namespace yaze {
12namespace app {
13namespace emu {
14
15void Cpu::Reset(bool hard) {
16 if (hard) {
17 A = 0;
18 X = 0;
19 Y = 0;
20 PC = 0;
21 PB = 0;
22 D = 0;
23 DB = 0;
24 E = 1;
25 status = 0x34;
26 irq_wanted_ = false;
27 }
28
29 reset_wanted_ = true;
30 stopped_ = false;
31 waiting_ = false;
32 nmi_wanted_ = false;
33 int_wanted_ = false;
34 int_delay_ = false;
35}
36
38 if (reset_wanted_) {
39 reset_wanted_ = false;
40 // reset: brk/interrupt without writes
41 auto sp = SP();
42
43 ReadByte((PB << 16) | PC);
44 callbacks_.idle(false);
45 ReadByte(0x100 | (sp-- & 0xff));
46 ReadByte(0x100 | (sp-- & 0xff));
47 ReadByte(0x100 | (sp-- & 0xff));
48 sp = (sp & 0xff) | 0x100;
49
50 SetSP(sp);
51
52 E = 1;
53 SetInterruptFlag(true);
54 SetDecimalFlag(false);
55 SetFlags(status); // updates x and m flags, clears
56 // upper half of x and y if needed
57 PB = 0;
58 PC = ReadWord(0xfffc, 0xfffd);
59 return;
60 }
61 if (stopped_) {
62 callbacks_.idle(true);
63 return;
64 }
65 if (waiting_) {
66 if (irq_wanted_ || nmi_wanted_) {
67 waiting_ = false;
68 callbacks_.idle(false);
69 CheckInt();
70 callbacks_.idle(false);
71 return;
72 } else {
73 callbacks_.idle(true);
74 return;
75 }
76 }
77 // not stopped or waiting, execute a opcode or go to interrupt
78 if (int_wanted_) {
79 ReadByte((PB << 16) | PC);
81 } else {
82 uint8_t opcode = ReadOpcode();
83 ExecuteInstruction(opcode);
84 }
85}
86
88 callbacks_.idle(false);
89 PushByte(PB);
90 PushWord(PC);
92 SetInterruptFlag(true);
93 SetDecimalFlag(false);
94 PB = 0;
95 int_wanted_ = false;
96 if (nmi_wanted_) {
97 nmi_wanted_ = false;
98 PC = ReadWord(0xffea, 0xffeb);
99 } else { // irq
100 PC = ReadWord(0xffee, 0xffef);
101 }
102}
103
104void Cpu::ExecuteInstruction(uint8_t opcode) {
105 uint8_t instruction_length = 0;
106 uint16_t cache_pc = PC;
107 uint32_t operand = 0;
108 bool immediate = false;
109 bool accumulator_mode = GetAccumulatorSize();
110
111 switch (opcode) {
112 case 0x00: { // brk imm(s)
113 uint32_t vector = (E) ? 0xfffe : 0xffe6;
114 ReadOpcode();
115 if (!E) PushByte(PB);
116 PushWord(PC, false);
118 SetInterruptFlag(true);
119 SetDecimalFlag(false);
120 PB = 0;
121 PC = ReadWord(vector, vector + 1, true);
122 break;
123 }
124 case 0x01: { // ora idx
125 uint32_t low = 0;
126 uint32_t high = AdrIdx(&low);
127 ORA(low, high);
128 break;
129 }
130 case 0x02: { // cop imm(s)
131 uint32_t vector = (E) ? 0xfff4 : 0xffe4;
132 ReadOpcode();
133 if (!E) PushByte(PB);
134 PushWord(PC, false);
136 SetInterruptFlag(true);
137 SetDecimalFlag(false);
138 PB = 0;
139 PC = ReadWord(vector, vector + 1, true);
140 break;
141 }
142 case 0x03: { // ora sr
143 uint32_t low = 0;
144 uint32_t high = AdrSr(&low);
145 ORA(low, high);
146 break;
147 }
148 case 0x04: { // tsb dp
149 uint32_t low = 0;
150 uint32_t high = AdrDp(&low);
151 Tsb(low, high);
152 break;
153 }
154 case 0x05: { // ora dp
155 uint32_t low = 0;
156 uint32_t high = AdrDp(&low);
157 ORA(low, high);
158 break;
159 }
160 case 0x06: { // asl dp
161 uint32_t low = 0;
162 uint32_t high = AdrDp(&low);
163 Asl(low, high);
164 break;
165 }
166 case 0x07: { // ora idl
167 uint32_t low = 0;
168 uint32_t high = AdrIdl(&low);
169 ORA(low, high);
170 break;
171 }
172 case 0x08: { // php imp
173 callbacks_.idle(false);
174 CheckInt();
176 break;
177 }
178 case 0x09: { // ora imm(m)
179 uint32_t low = 0;
180 uint32_t high = Immediate(&low, false);
181 ORA(low, high);
182 break;
183 }
184 case 0x0a: { // asla imp
185 AdrImp();
186 if (GetAccumulatorSize()) {
187 SetCarryFlag(A & 0x80);
188 A = (A & 0xff00) | ((A << 1) & 0xff);
189 } else {
190 SetCarryFlag(A & 0x8000);
191 A <<= 1;
192 }
194 break;
195 }
196 case 0x0b: { // phd imp
197 callbacks_.idle(false);
198 PushWord(D, true);
199 break;
200 }
201 case 0x0c: { // tsb abs
202 uint32_t low = 0;
203 uint32_t high = Absolute(&low);
204 Tsb(low, high);
205 break;
206 }
207 case 0x0d: { // ora abs
208 uint32_t low = 0;
209 uint32_t high = Absolute(&low);
210 ORA(low, high);
211 break;
212 }
213 case 0x0e: { // asl abs
214 uint32_t low = 0;
215 uint32_t high = Absolute(&low);
216 Asl(low, high);
217 break;
218 }
219 case 0x0f: { // ora abl
220 uint32_t low = 0;
221 uint32_t high = AdrAbl(&low);
222 ORA(low, high);
223 break;
224 }
225 case 0x10: { // bpl rel
227 break;
228 }
229 case 0x11: { // ora idy(r)
230 uint32_t low = 0;
231 uint32_t high = AdrIdy(&low, false);
232 ORA(low, high);
233 break;
234 }
235 case 0x12: { // ora idp
236 uint32_t low = 0;
237 uint32_t high = AdrIdp(&low);
238 ORA(low, high);
239 break;
240 }
241 case 0x13: { // ora isy
242 uint32_t low = 0;
243 uint32_t high = AdrIsy(&low);
244 ORA(low, high);
245 break;
246 }
247 case 0x14: { // trb dp
248 uint32_t low = 0;
249 uint32_t high = AdrDp(&low);
250 Trb(low, high);
251 break;
252 }
253 case 0x15: { // ora dpx
254 uint32_t low = 0;
255 uint32_t high = AdrDpx(&low);
256 ORA(low, high);
257 break;
258 }
259 case 0x16: { // asl dpx
260 uint32_t low = 0;
261 uint32_t high = AdrDpx(&low);
262 Asl(low, high);
263 break;
264 }
265 case 0x17: { // ora ily
266 uint32_t low = 0;
267 uint32_t high = AdrIly(&low);
268 ORA(low, high);
269 break;
270 }
271 case 0x18: { // clc imp
272 AdrImp();
273 SetCarryFlag(false);
274 break;
275 }
276 case 0x19: { // ora aby(r)
277 uint32_t low = 0;
278 uint32_t high = AdrAby(&low, false);
279 ORA(low, high);
280 break;
281 }
282 case 0x1a: { // inca imp
283 AdrImp();
284 if (GetAccumulatorSize()) {
285 A = (A & 0xff00) | ((A + 1) & 0xff);
286 } else {
287 A++;
288 }
290 break;
291 }
292 case 0x1b: { // tcs imp
293 AdrImp();
294 SetSP(A);
295 break;
296 }
297 case 0x1c: { // trb abs
298 uint32_t low = 0;
299 uint32_t high = Absolute(&low);
300 Trb(low, high);
301 break;
302 }
303 case 0x1d: { // ora abx(r)
304 uint32_t low = 0;
305 uint32_t high = AdrAbx(&low, false);
306 ORA(low, high);
307 break;
308 }
309 case 0x1e: { // asl abx
310 uint32_t low = 0;
311 uint32_t high = AdrAbx(&low, true);
312 Asl(low, high);
313 break;
314 }
315 case 0x1f: { // ora alx
316 uint32_t low = 0;
317 uint32_t high = AdrAlx(&low);
318 ORA(low, high);
319 break;
320 }
321 case 0x20: { // jsr abs
322 uint16_t value = ReadOpcodeWord(false);
323 callbacks_.idle(false);
324 PushWord(PC - 1, true);
325 PC = value;
326 break;
327 }
328 case 0x21: { // and idx
329 uint32_t low = 0;
330 uint32_t high = AdrIdx(&low);
331 And(low, high);
332 break;
333 }
334 case 0x22: { // jsl abl
335 uint16_t value = ReadOpcodeWord(false);
336 PushByte(PB);
337 callbacks_.idle(false);
338 uint8_t newK = ReadOpcode();
339 PushWord(PC - 1, true);
340 PC = value;
341 PB = newK;
342 break;
343 }
344 case 0x23: { // and sr
345 uint32_t low = 0;
346 uint32_t high = AdrSr(&low);
347 And(low, high);
348 break;
349 }
350 case 0x24: { // bit dp
351 uint32_t low = 0;
352 uint32_t high = AdrDp(&low);
353 Bit(low, high);
354 break;
355 }
356 case 0x25: { // and dp
357 uint32_t low = 0;
358 uint32_t high = AdrDp(&low);
359 And(low, high);
360 break;
361 }
362 case 0x26: { // rol dp
363 uint32_t low = 0;
364 uint32_t high = AdrDp(&low);
365 Rol(low, high);
366 break;
367 }
368 case 0x27: { // and idl
369 uint32_t low = 0;
370 uint32_t high = AdrIdl(&low);
371 And(low, high);
372 break;
373 }
374 case 0x28: { // plp imp
375 callbacks_.idle(false);
376 callbacks_.idle(false);
377 CheckInt();
378 SetFlags(PopByte());
379 break;
380 }
381 case 0x29: { // and imm(m)
382 uint32_t low = 0;
383 uint32_t high = Immediate(&low, false);
384 And(low, high);
385 break;
386 }
387 case 0x2a: { // rola imp
388 AdrImp();
389 int result = (A << 1) | GetCarryFlag();
390 if (GetAccumulatorSize()) {
391 SetCarryFlag(result & 0x100);
392 A = (A & 0xff00) | (result & 0xff);
393 } else {
394 SetCarryFlag(result & 0x10000);
395 A = result;
396 }
398 break;
399 }
400 case 0x2b: { // pld imp
401 callbacks_.idle(false);
402 callbacks_.idle(false);
403 D = PopWord(true);
404 SetZN(D, false);
405 break;
406 }
407 case 0x2c: { // bit abs
408 uint32_t low = 0;
409 uint32_t high = Absolute(&low);
410 Bit(low, high);
411 break;
412 }
413 case 0x2d: { // and abs
414 uint32_t low = 0;
415 uint32_t high = Absolute(&low);
416 And(low, high);
417 break;
418 }
419 case 0x2e: { // rol abs
420 uint32_t low = 0;
421 uint32_t high = Absolute(&low);
422 Rol(low, high);
423 break;
424 }
425 case 0x2f: { // and abl
426 uint32_t low = 0;
427 uint32_t high = AdrAbl(&low);
428 And(low, high);
429 break;
430 }
431 case 0x30: { // bmi rel
433 break;
434 }
435 case 0x31: { // and idy(r)
436 uint32_t low = 0;
437 uint32_t high = AdrIdy(&low, false);
438 And(low, high);
439 break;
440 }
441 case 0x32: { // and idp
442 uint32_t low = 0;
443 uint32_t high = AdrIdp(&low);
444 And(low, high);
445 break;
446 }
447 case 0x33: { // and isy
448 uint32_t low = 0;
449 uint32_t high = AdrIsy(&low);
450 And(low, high);
451 break;
452 }
453 case 0x34: { // bit dpx
454 uint32_t low = 0;
455 uint32_t high = AdrDpx(&low);
456 Bit(low, high);
457 break;
458 }
459 case 0x35: { // and dpx
460 uint32_t low = 0;
461 uint32_t high = AdrDpx(&low);
462 And(low, high);
463 break;
464 }
465 case 0x36: { // rol dpx
466 uint32_t low = 0;
467 uint32_t high = AdrDpx(&low);
468 Rol(low, high);
469 break;
470 }
471 case 0x37: { // and ily
472 uint32_t low = 0;
473 uint32_t high = AdrIly(&low);
474 And(low, high);
475 break;
476 }
477 case 0x38: { // sec imp
478 AdrImp();
479 SetCarryFlag(true);
480 break;
481 }
482 case 0x39: { // and aby(r)
483 uint32_t low = 0;
484 uint32_t high = AdrAby(&low, false);
485 And(low, high);
486 break;
487 }
488 case 0x3a: { // deca imp
489 AdrImp();
490 if (GetAccumulatorSize()) {
491 A = (A & 0xff00) | ((A - 1) & 0xff);
492 } else {
493 A--;
494 }
496 break;
497 }
498 case 0x3b: { // tsc imp
499 AdrImp();
500 A = SP();
501 SetZN(A, false);
502 break;
503 }
504 case 0x3c: { // bit abx(r)
505 uint32_t low = 0;
506 uint32_t high = AdrAbx(&low, false);
507 Bit(low, high);
508 break;
509 }
510 case 0x3d: { // and abx(r)
511 uint32_t low = 0;
512 uint32_t high = AdrAbx(&low, false);
513 And(low, high);
514 break;
515 }
516 case 0x3e: { // rol abx
517 uint32_t low = 0;
518 uint32_t high = AdrAbx(&low, true);
519 Rol(low, high);
520 break;
521 }
522 case 0x3f: { // and alx
523 uint32_t low = 0;
524 uint32_t high = AdrAlx(&low);
525 And(low, high);
526 break;
527 }
528 case 0x40: { // rti imp
529 callbacks_.idle(false);
530 callbacks_.idle(false);
531 SetFlags(PopByte());
532 PC = PopWord(false);
533 CheckInt();
534 PB = PopByte();
535 break;
536 }
537 case 0x41: { // eor idx
538 uint32_t low = 0;
539 uint32_t high = AdrIdx(&low);
540 Eor(low, high);
541 break;
542 }
543 case 0x42: { // wdm imm(s)
544 CheckInt();
545 ReadOpcode();
546 break;
547 }
548 case 0x43: { // eor sr
549 uint32_t low = 0;
550 uint32_t high = AdrSr(&low);
551 Eor(low, high);
552 break;
553 }
554 case 0x44: { // mvp bm
555 uint8_t dest = ReadOpcode();
556 uint8_t src = ReadOpcode();
557 DB = dest;
558 WriteByte((dest << 16) | Y, ReadByte((src << 16) | X));
559 A--;
560 X--;
561 Y--;
562 if (A != 0xffff) {
563 PC -= 3;
564 }
565 if (GetIndexSize()) {
566 X &= 0xff;
567 Y &= 0xff;
568 }
569 callbacks_.idle(false);
570 CheckInt();
571 callbacks_.idle(false);
572 break;
573 }
574 case 0x45: { // eor dp
575 uint32_t low = 0;
576 uint32_t high = AdrDp(&low);
577 Eor(low, high);
578 break;
579 }
580 case 0x46: { // lsr dp
581 uint32_t low = 0;
582 uint32_t high = AdrDp(&low);
583 Lsr(low, high);
584 break;
585 }
586 case 0x47: { // eor idl
587 uint32_t low = 0;
588 uint32_t high = AdrIdl(&low);
589 Eor(low, high);
590 break;
591 }
592 case 0x48: { // pha imp
593 callbacks_.idle(false);
594 if (GetAccumulatorSize()) {
595 CheckInt();
596 PushByte(A);
597 } else {
598 PushWord(A, true);
599 }
600 break;
601 }
602 case 0x49: { // eor imm(m)
603 uint32_t low = 0;
604 uint32_t high = Immediate(&low, false);
605 Eor(low, high);
606 break;
607 }
608 case 0x4a: { // lsra imp
609 AdrImp();
610 SetCarryFlag(A & 1);
611 if (GetAccumulatorSize()) {
612 A = (A & 0xff00) | ((A >> 1) & 0x7f);
613 } else {
614 A >>= 1;
615 }
617 break;
618 }
619 case 0x4b: { // phk imp
620 callbacks_.idle(false);
621 CheckInt();
622 PushByte(PB);
623 break;
624 }
625 case 0x4c: { // jmp abs
626 PC = ReadOpcodeWord(true);
627 break;
628 }
629 case 0x4d: { // eor abs
630 uint32_t low = 0;
631 uint32_t high = Absolute(&low);
632 Eor(low, high);
633 break;
634 }
635 case 0x4e: { // lsr abs
636 uint32_t low = 0;
637 uint32_t high = Absolute(&low);
638 Lsr(low, high);
639 break;
640 }
641 case 0x4f: { // eor abl
642 uint32_t low = 0;
643 uint32_t high = AdrAbl(&low);
644 Eor(low, high);
645 break;
646 }
647 case 0x50: { // bvc rel
649 break;
650 }
651 case 0x51: { // eor idy(r)
652 uint32_t low = 0;
653 uint32_t high = AdrIdy(&low, false);
654 Eor(low, high);
655 break;
656 }
657 case 0x52: { // eor idp
658 uint32_t low = 0;
659 uint32_t high = AdrIdp(&low);
660 Eor(low, high);
661 break;
662 }
663 case 0x53: { // eor isy
664 uint32_t low = 0;
665 uint32_t high = AdrIsy(&low);
666 Eor(low, high);
667 break;
668 }
669 case 0x54: { // mvn bm
670 uint8_t dest = ReadOpcode();
671 uint8_t src = ReadOpcode();
672 DB = dest;
673 WriteByte((dest << 16) | Y, ReadByte((src << 16) | X));
674 A--;
675 X++;
676 Y++;
677 if (A != 0xffff) {
678 PC -= 3;
679 }
680 if (GetIndexSize()) {
681 X &= 0xff;
682 Y &= 0xff;
683 }
684 callbacks_.idle(false);
685 CheckInt();
686 callbacks_.idle(false);
687 break;
688 }
689 case 0x55: { // eor dpx
690 uint32_t low = 0;
691 uint32_t high = AdrDpx(&low);
692 Eor(low, high);
693 break;
694 }
695 case 0x56: { // lsr dpx
696 uint32_t low = 0;
697 uint32_t high = AdrDpx(&low);
698 Lsr(low, high);
699 break;
700 }
701 case 0x57: { // eor ily
702 uint32_t low = 0;
703 uint32_t high = AdrIly(&low);
704 Eor(low, high);
705 break;
706 }
707 case 0x58: { // cli imp
708 AdrImp();
709 SetInterruptFlag(false);
710 break;
711 }
712 case 0x59: { // eor aby(r)
713 uint32_t low = 0;
714 uint32_t high = AdrAby(&low, false);
715 Eor(low, high);
716 break;
717 }
718 case 0x5a: { // phy imp
719 callbacks_.idle(false);
720 if (GetIndexSize()) {
721 CheckInt();
722 PushByte(Y);
723 } else {
724 PushWord(Y, true);
725 }
726 break;
727 }
728 case 0x5b: { // tcd imp
729 AdrImp();
730 D = A;
731 SetZN(D, false);
732 break;
733 }
734 case 0x5c: { // jml abl
735 uint16_t value = ReadOpcodeWord(false);
736 CheckInt();
737 PB = ReadOpcode();
738 PC = value;
739 break;
740 }
741 case 0x5d: { // eor abx(r)
742 uint32_t low = 0;
743 uint32_t high = AdrAbx(&low, false);
744 Eor(low, high);
745 break;
746 }
747 case 0x5e: { // lsr abx
748 uint32_t low = 0;
749 uint32_t high = AdrAbx(&low, true);
750 Lsr(low, high);
751 break;
752 }
753 case 0x5f: { // eor alx
754 uint32_t low = 0;
755 uint32_t high = AdrAlx(&low);
756 Eor(low, high);
757 break;
758 }
759 case 0x60: { // rts imp
760 callbacks_.idle(false);
761 callbacks_.idle(false);
762 PC = PopWord(false) + 1;
763 CheckInt();
764 callbacks_.idle(false);
765 break;
766 }
767 case 0x61: { // adc idx
768 uint32_t low = 0;
769 uint32_t high = AdrIdx(&low);
770 Adc(low, high);
771 break;
772 }
773 case 0x62: { // per rll
774 uint16_t value = ReadOpcodeWord(false);
775 callbacks_.idle(false);
776 PushWord(PC + (int16_t)value, true);
777 break;
778 }
779 case 0x63: { // adc sr
780 uint32_t low = 0;
781 uint32_t high = AdrSr(&low);
782 Adc(low, high);
783 break;
784 }
785 case 0x64: { // stz dp
786 uint32_t low = 0;
787 uint32_t high = AdrDp(&low);
788 Stz(low, high);
789 break;
790 }
791 case 0x65: { // adc dp
792 uint32_t low = 0;
793 uint32_t high = AdrDp(&low);
794 Adc(low, high);
795 break;
796 }
797 case 0x66: { // ror dp
798 uint32_t low = 0;
799 uint32_t high = AdrDp(&low);
800 Ror(low, high);
801 break;
802 }
803 case 0x67: { // adc idl
804 uint32_t low = 0;
805 uint32_t high = AdrIdl(&low);
806 Adc(low, high);
807 break;
808 }
809 case 0x68: { // pla imp
810 callbacks_.idle(false);
811 callbacks_.idle(false);
812 if (GetAccumulatorSize()) {
813 CheckInt();
814 A = (A & 0xff00) | PopByte();
815 } else {
816 A = PopWord(true);
817 }
819 break;
820 }
821 case 0x69: { // adc imm(m)
822 uint32_t low = 0;
823 uint32_t high = Immediate(&low, false);
824 Adc(low, high);
825 break;
826 }
827 case 0x6a: { // rora imp
828 AdrImp();
829 bool carry = A & 1;
830 auto C = GetCarryFlag();
831 if (GetAccumulatorSize()) {
832 A = (A & 0xff00) | ((A >> 1) & 0x7f) | (C << 7);
833 } else {
834 A = (A >> 1) | (C << 15);
835 }
836 SetCarryFlag(carry);
838 break;
839 }
840 case 0x6b: { // rtl imp
841 callbacks_.idle(false);
842 callbacks_.idle(false);
843 PC = PopWord(false) + 1;
844 CheckInt();
845 PB = PopByte();
846 break;
847 }
848 case 0x6c: { // jmp ind
849 uint16_t adr = ReadOpcodeWord(false);
850 PC = ReadWord(adr, (adr + 1) & 0xffff, true);
851 break;
852 }
853 case 0x6d: { // adc abs
854 uint32_t low = 0;
855 uint32_t high = Absolute(&low);
856 Adc(low, high);
857 break;
858 }
859 case 0x6e: { // ror abs
860 uint32_t low = 0;
861 uint32_t high = Absolute(&low);
862 Ror(low, high);
863 break;
864 }
865 case 0x6f: { // adc abl
866 uint32_t low = 0;
867 uint32_t high = AdrAbl(&low);
868 Adc(low, high);
869 break;
870 }
871 case 0x70: { // bvs rel
873 break;
874 }
875 case 0x71: { // adc idy(r)
876 uint32_t low = 0;
877 uint32_t high = AdrIdy(&low, false);
878 Adc(low, high);
879 break;
880 }
881 case 0x72: { // adc idp
882 uint32_t low = 0;
883 uint32_t high = AdrIdp(&low);
884 Adc(low, high);
885 break;
886 }
887 case 0x73: { // adc isy
888 uint32_t low = 0;
889 uint32_t high = AdrIsy(&low);
890 Adc(low, high);
891 break;
892 }
893 case 0x74: { // stz dpx
894 uint32_t low = 0;
895 uint32_t high = AdrDpx(&low);
896 Stz(low, high);
897 break;
898 }
899 case 0x75: { // adc dpx
900 uint32_t low = 0;
901 uint32_t high = AdrDpx(&low);
902 Adc(low, high);
903 break;
904 }
905 case 0x76: { // ror dpx
906 uint32_t low = 0;
907 uint32_t high = AdrDpx(&low);
908 Ror(low, high);
909 break;
910 }
911 case 0x77: { // adc ily
912 uint32_t low = 0;
913 uint32_t high = AdrIly(&low);
914 Adc(low, high);
915 break;
916 }
917 case 0x78: { // sei imp
918 AdrImp();
919 SetInterruptFlag(true);
920 break;
921 }
922 case 0x79: { // adc aby(r)
923 uint32_t low = 0;
924 uint32_t high = AdrAby(&low, false);
925 Adc(low, high);
926 break;
927 }
928 case 0x7a: { // ply imp
929 callbacks_.idle(false);
930 callbacks_.idle(false);
931 if (GetIndexSize()) {
932 CheckInt();
933 Y = PopByte();
934 } else {
935 Y = PopWord(true);
936 }
937 SetZN(Y, GetIndexSize());
938 break;
939 }
940 case 0x7b: { // tdc imp
941 AdrImp();
942 A = D;
943 SetZN(A, false);
944 break;
945 }
946 case 0x7c: { // jmp iax
947 uint16_t adr = ReadOpcodeWord(false);
948 callbacks_.idle(false);
949 PC = ReadWord((PB << 16) | ((adr + X) & 0xffff),
950 ((PB << 16) | ((adr + X + 1) & 0xffff)), true);
951 break;
952 }
953 case 0x7d: { // adc abx(r)
954 uint32_t low = 0;
955 uint32_t high = AdrAbx(&low, false);
956 Adc(low, high);
957 break;
958 }
959 case 0x7e: { // ror abx
960 uint32_t low = 0;
961 uint32_t high = AdrAbx(&low, true);
962 Ror(low, high);
963 break;
964 }
965 case 0x7f: { // adc alx
966 uint32_t low = 0;
967 uint32_t high = AdrAlx(&low);
968 Adc(low, high);
969 break;
970 }
971 case 0x80: { // bra rel
972 DoBranch(true);
973 break;
974 }
975 case 0x81: { // sta idx
976 uint32_t low = 0;
977 uint32_t high = AdrIdx(&low);
978 Sta(low, high);
979 break;
980 }
981 case 0x82: { // brl rll
982 PC += (int16_t)ReadOpcodeWord(false);
983 CheckInt();
984 callbacks_.idle(false);
985 break;
986 }
987 case 0x83: { // sta sr
988 uint32_t low = 0;
989 uint32_t high = AdrSr(&low);
990 Sta(low, high);
991 break;
992 }
993 case 0x84: { // sty dp
994 uint32_t low = 0;
995 uint32_t high = AdrDp(&low);
996 Sty(low, high);
997 break;
998 }
999 case 0x85: { // sta dp
1000 uint32_t low = 0;
1001 uint32_t high = AdrDp(&low);
1002 Sta(low, high);
1003 break;
1004 }
1005 case 0x86: { // stx dp
1006 uint32_t low = 0;
1007 uint32_t high = AdrDp(&low);
1008 Stx(low, high);
1009 break;
1010 }
1011 case 0x87: { // sta idl
1012 uint32_t low = 0;
1013 uint32_t high = AdrIdl(&low);
1014 Sta(low, high);
1015 break;
1016 }
1017 case 0x88: { // dey imp
1018 AdrImp();
1019 if (GetIndexSize()) {
1020 Y = (Y - 1) & 0xff;
1021 } else {
1022 Y--;
1023 }
1024 SetZN(Y, GetIndexSize());
1025 break;
1026 }
1027 case 0x89: { // biti imm(m)
1028 if (GetAccumulatorSize()) {
1029 CheckInt();
1030 uint8_t result = (A & 0xff) & ReadOpcode();
1031 SetZeroFlag(result == 0);
1032 } else {
1033 uint16_t result = A & ReadOpcodeWord(true);
1034 SetZeroFlag(result == 0);
1035 }
1036 break;
1037 }
1038 case 0x8a: { // txa imp
1039 AdrImp();
1040 if (GetAccumulatorSize()) {
1041 A = (A & 0xff00) | (X & 0xff);
1042 } else {
1043 A = X;
1044 }
1046 break;
1047 }
1048 case 0x8b: { // phb imp
1049 callbacks_.idle(false);
1050 CheckInt();
1051 PushByte(DB);
1052 break;
1053 }
1054 case 0x8c: { // sty abs
1055 uint32_t low = 0;
1056 uint32_t high = Absolute(&low);
1057 Sty(low, high);
1058 break;
1059 }
1060 case 0x8d: { // sta abs
1061 uint32_t low = 0;
1062 uint32_t high = Absolute(&low);
1063 Sta(low, high);
1064 break;
1065 }
1066 case 0x8e: { // stx abs
1067 uint32_t low = 0;
1068 uint32_t high = Absolute(&low);
1069 Stx(low, high);
1070 break;
1071 }
1072 case 0x8f: { // sta abl
1073 uint32_t low = 0;
1074 uint32_t high = AdrAbl(&low);
1075 Sta(low, high);
1076 break;
1077 }
1078 case 0x90: { // bcc rel
1080 break;
1081 }
1082 case 0x91: { // sta idy
1083 uint32_t low = 0;
1084 uint32_t high = AdrIdy(&low, true);
1085 Sta(low, high);
1086 break;
1087 }
1088 case 0x92: { // sta idp
1089 uint32_t low = 0;
1090 uint32_t high = AdrIdp(&low);
1091 Sta(low, high);
1092 break;
1093 }
1094 case 0x93: { // sta isy
1095 uint32_t low = 0;
1096 uint32_t high = AdrIsy(&low);
1097 Sta(low, high);
1098 break;
1099 }
1100 case 0x94: { // sty dpx
1101 uint32_t low = 0;
1102 uint32_t high = AdrDpx(&low);
1103 Sty(low, high);
1104 break;
1105 }
1106 case 0x95: { // sta dpx
1107 uint32_t low = 0;
1108 uint32_t high = AdrDpx(&low);
1109 Sta(low, high);
1110 break;
1111 }
1112 case 0x96: { // stx dpy
1113 uint32_t low = 0;
1114 uint32_t high = AdrDpy(&low);
1115 Stx(low, high);
1116 break;
1117 }
1118 case 0x97: { // sta ily
1119 uint32_t low = 0;
1120 uint32_t high = AdrIly(&low);
1121 Sta(low, high);
1122 break;
1123 }
1124 case 0x98: { // tya imp
1125 AdrImp();
1126 if (GetAccumulatorSize()) {
1127 A = (A & 0xff00) | (Y & 0xff);
1128 } else {
1129 A = Y;
1130 }
1132 break;
1133 }
1134 case 0x99: { // sta aby
1135 uint32_t low = 0;
1136 uint32_t high = AdrAby(&low, true);
1137 Sta(low, high);
1138 break;
1139 }
1140 case 0x9a: { // txs imp
1141 AdrImp();
1142 SetSP(X);
1143 break;
1144 }
1145 case 0x9b: { // txy imp
1146 AdrImp();
1147 if (GetIndexSize()) {
1148 Y = X & 0xff;
1149 } else {
1150 Y = X;
1151 }
1152 SetZN(Y, GetIndexSize());
1153 break;
1154 }
1155 case 0x9c: { // stz abs
1156 uint32_t low = 0;
1157 uint32_t high = Absolute(&low);
1158 Stz(low, high);
1159 break;
1160 }
1161 case 0x9d: { // sta abx
1162 uint32_t low = 0;
1163 uint32_t high = AdrAbx(&low, true);
1164 Sta(low, high);
1165 break;
1166 }
1167 case 0x9e: { // stz abx
1168 uint32_t low = 0;
1169 uint32_t high = AdrAbx(&low, true);
1170 Stz(low, high);
1171 break;
1172 }
1173 case 0x9f: { // sta alx
1174 uint32_t low = 0;
1175 uint32_t high = AdrAlx(&low);
1176 Sta(low, high);
1177 break;
1178 }
1179 case 0xa0: { // ldy imm(x)
1180 uint32_t low = 0;
1181 uint32_t high = Immediate(&low, true);
1182 Ldy(low, high);
1183 break;
1184 }
1185 case 0xa1: { // lda idx
1186 uint32_t low = 0;
1187 uint32_t high = AdrIdx(&low);
1188 Lda(low, high);
1189 break;
1190 }
1191 case 0xa2: { // ldx imm(x)
1192 uint32_t low = 0;
1193 uint32_t high = Immediate(&low, true);
1194 Ldx(low, high);
1195 break;
1196 }
1197 case 0xa3: { // lda sr
1198 uint32_t low = 0;
1199 uint32_t high = AdrSr(&low);
1200 Lda(low, high);
1201 break;
1202 }
1203 case 0xa4: { // ldy dp
1204 uint32_t low = 0;
1205 uint32_t high = AdrDp(&low);
1206 Ldy(low, high);
1207 break;
1208 }
1209 case 0xa5: { // lda dp
1210 uint32_t low = 0;
1211 uint32_t high = AdrDp(&low);
1212 Lda(low, high);
1213 break;
1214 }
1215 case 0xa6: { // ldx dp
1216 uint32_t low = 0;
1217 uint32_t high = AdrDp(&low);
1218 Ldx(low, high);
1219 break;
1220 }
1221 case 0xa7: { // lda idl
1222 uint32_t low = 0;
1223 uint32_t high = AdrIdl(&low);
1224 Lda(low, high);
1225 break;
1226 }
1227 case 0xa8: { // tay imp
1228 AdrImp();
1229 if (GetIndexSize()) {
1230 Y = A & 0xff;
1231 } else {
1232 Y = A;
1233 }
1234 SetZN(Y, GetIndexSize());
1235 break;
1236 }
1237 case 0xa9: { // lda imm(m)
1238 uint32_t low = 0;
1239 uint32_t high = Immediate(&low, false);
1240 Lda(low, high);
1241 break;
1242 }
1243 case 0xaa: { // tax imp
1244 AdrImp();
1245 if (GetIndexSize()) {
1246 X = A & 0xff;
1247 } else {
1248 X = A;
1249 }
1250 SetZN(X, GetIndexSize());
1251 break;
1252 }
1253 case 0xab: { // plb imp
1254 callbacks_.idle(false);
1255 callbacks_.idle(false);
1256 CheckInt();
1257 DB = PopByte();
1258 SetZN(DB, true);
1259 break;
1260 }
1261 case 0xac: { // ldy abs
1262 uint32_t low = 0;
1263 uint32_t high = Absolute(&low);
1264 Ldy(low, high);
1265 break;
1266 }
1267 case 0xad: { // lda abs
1268 uint32_t low = 0;
1269 uint32_t high = Absolute(&low);
1270 Lda(low, high);
1271 break;
1272 }
1273 case 0xae: { // ldx abs
1274 uint32_t low = 0;
1275 uint32_t high = Absolute(&low);
1276 Ldx(low, high);
1277 break;
1278 }
1279 case 0xaf: { // lda abl
1280 uint32_t low = 0;
1281 uint32_t high = AdrAbl(&low);
1282 Lda(low, high);
1283 break;
1284 }
1285 case 0xb0: { // bcs rel
1287 break;
1288 }
1289 case 0xb1: { // lda idy(r)
1290 uint32_t low = 0;
1291 uint32_t high = AdrIdy(&low, false);
1292 Lda(low, high);
1293 break;
1294 }
1295 case 0xb2: { // lda idp
1296 uint32_t low = 0;
1297 uint32_t high = AdrIdp(&low);
1298 Lda(low, high);
1299 break;
1300 }
1301 case 0xb3: { // lda isy
1302 uint32_t low = 0;
1303 uint32_t high = AdrIsy(&low);
1304 Lda(low, high);
1305 break;
1306 }
1307 case 0xb4: { // ldy dpx
1308 uint32_t low = 0;
1309 uint32_t high = AdrDpx(&low);
1310 Ldy(low, high);
1311 break;
1312 }
1313 case 0xb5: { // lda dpx
1314 uint32_t low = 0;
1315 uint32_t high = AdrDpx(&low);
1316 Lda(low, high);
1317 break;
1318 }
1319 case 0xb6: { // ldx dpy
1320 uint32_t low = 0;
1321 uint32_t high = AdrDpy(&low);
1322 Ldx(low, high);
1323 break;
1324 }
1325 case 0xb7: { // lda ily
1326 uint32_t low = 0;
1327 uint32_t high = AdrIly(&low);
1328 Lda(low, high);
1329 break;
1330 }
1331 case 0xb8: { // clv imp
1332 AdrImp();
1333 SetOverflowFlag(false);
1334 break;
1335 }
1336 case 0xb9: { // lda aby(r)
1337 uint32_t low = 0;
1338 uint32_t high = AdrAby(&low, false);
1339 Lda(low, high);
1340 break;
1341 }
1342 case 0xba: { // tsx imp
1343 AdrImp();
1344 if (GetIndexSize()) {
1345 SetSP(X & 0xff);
1346 } else {
1347 SetSP(X);
1348 }
1349 SetZN(X, GetIndexSize());
1350 break;
1351 }
1352 case 0xbb: { // tyx imp
1353 AdrImp();
1354 if (GetIndexSize()) {
1355 X = Y & 0xff;
1356 } else {
1357 X = Y;
1358 }
1359 SetZN(X, GetIndexSize());
1360 break;
1361 }
1362 case 0xbc: { // ldy abx(r)
1363 uint32_t low = 0;
1364 uint32_t high = AdrAbx(&low, false);
1365 Ldy(low, high);
1366 break;
1367 }
1368 case 0xbd: { // lda abx(r)
1369 uint32_t low = 0;
1370 uint32_t high = AdrAbx(&low, false);
1371 Lda(low, high);
1372 break;
1373 }
1374 case 0xbe: { // ldx aby(r)
1375 uint32_t low = 0;
1376 uint32_t high = AdrAby(&low, false);
1377 Ldx(low, high);
1378 break;
1379 }
1380 case 0xbf: { // lda alx
1381 uint32_t low = 0;
1382 uint32_t high = AdrAlx(&low);
1383 Lda(low, high);
1384 break;
1385 }
1386 case 0xc0: { // cpy imm(x)
1387 uint32_t low = 0;
1388 uint32_t high = Immediate(&low, true);
1389 Cpy(low, high);
1390 break;
1391 }
1392 case 0xc1: { // cmp idx
1393 uint32_t low = 0;
1394 uint32_t high = AdrIdx(&low);
1395 Cmp(low, high);
1396 break;
1397 }
1398 case 0xc2: { // rep imm(s)
1399 uint8_t val = ReadOpcode();
1400 CheckInt();
1401 SetFlags(status & ~val);
1402 callbacks_.idle(false);
1403 break;
1404 }
1405 case 0xc3: { // cmp sr
1406 uint32_t low = 0;
1407 uint32_t high = AdrSr(&low);
1408 Cmp(low, high);
1409 break;
1410 }
1411 case 0xc4: { // cpy dp
1412 uint32_t low = 0;
1413 uint32_t high = AdrDp(&low);
1414 Cpy(low, high);
1415 break;
1416 }
1417 case 0xc5: { // cmp dp
1418 uint32_t low = 0;
1419 uint32_t high = AdrDp(&low);
1420 Cmp(low, high);
1421 break;
1422 }
1423 case 0xc6: { // dec dp
1424 uint32_t low = 0;
1425 uint32_t high = AdrDp(&low);
1426 Dec(low, high);
1427 break;
1428 }
1429 case 0xc7: { // cmp idl
1430 uint32_t low = 0;
1431 uint32_t high = AdrIdl(&low);
1432 Cmp(low, high);
1433 break;
1434 }
1435 case 0xc8: { // iny imp
1436 AdrImp();
1437 if (GetIndexSize()) {
1438 Y = (Y + 1) & 0xff;
1439 } else {
1440 Y++;
1441 }
1442 SetZN(Y, GetIndexSize());
1443 break;
1444 }
1445 case 0xc9: { // cmp imm(m)
1446 uint32_t low = 0;
1447 uint32_t high = Immediate(&low, false);
1448 Cmp(low, high);
1449 break;
1450 }
1451 case 0xca: { // dex imp
1452 AdrImp();
1453 if (GetIndexSize()) {
1454 X = (X - 1) & 0xff;
1455 } else {
1456 X--;
1457 }
1458 SetZN(X, GetIndexSize());
1459 break;
1460 }
1461 case 0xcb: { // wai imp
1462 waiting_ = true;
1463 callbacks_.idle(false);
1464 callbacks_.idle(false);
1465 break;
1466 }
1467 case 0xcc: { // cpy abs
1468 uint32_t low = 0;
1469 uint32_t high = Absolute(&low);
1470 Cpy(low, high);
1471 break;
1472 }
1473 case 0xcd: { // cmp abs
1474 uint32_t low = 0;
1475 uint32_t high = Absolute(&low);
1476 Cmp(low, high);
1477 break;
1478 }
1479 case 0xce: { // dec abs
1480 uint32_t low = 0;
1481 uint32_t high = Absolute(&low);
1482 Dec(low, high);
1483 break;
1484 }
1485 case 0xcf: { // cmp abl
1486 uint32_t low = 0;
1487 uint32_t high = AdrAbl(&low);
1488 Cmp(low, high);
1489 break;
1490 }
1491 case 0xd0: { // bne rel
1493 break;
1494 }
1495 case 0xd1: { // cmp idy(r)
1496 uint32_t low = 0;
1497 uint32_t high = AdrIdy(&low, false);
1498 Cmp(low, high);
1499 break;
1500 }
1501 case 0xd2: { // cmp idp
1502 uint32_t low = 0;
1503 uint32_t high = AdrIdp(&low);
1504 Cmp(low, high);
1505 break;
1506 }
1507 case 0xd3: { // cmp isy
1508 uint32_t low = 0;
1509 uint32_t high = AdrIsy(&low);
1510 Cmp(low, high);
1511 break;
1512 }
1513 case 0xd4: { // pei dp
1514 uint32_t low = 0;
1515 uint32_t high = AdrDp(&low);
1516 PushWord(ReadWord(low, high, false), true);
1517 break;
1518 }
1519 case 0xd5: { // cmp dpx
1520 uint32_t low = 0;
1521 uint32_t high = AdrDpx(&low);
1522 Cmp(low, high);
1523 break;
1524 }
1525 case 0xd6: { // dec dpx
1526 uint32_t low = 0;
1527 uint32_t high = AdrDpx(&low);
1528 Dec(low, high);
1529 break;
1530 }
1531 case 0xd7: { // cmp ily
1532 uint32_t low = 0;
1533 uint32_t high = AdrIly(&low);
1534 Cmp(low, high);
1535 break;
1536 }
1537 case 0xd8: { // cld imp
1538 AdrImp();
1539 SetDecimalFlag(false);
1540 break;
1541 }
1542 case 0xd9: { // cmp aby(r)
1543 uint32_t low = 0;
1544 uint32_t high = AdrAby(&low, false);
1545 Cmp(low, high);
1546 break;
1547 }
1548 case 0xda: { // phx imp
1549 callbacks_.idle(false);
1550 if (GetIndexSize()) {
1551 CheckInt();
1552 PushByte(X);
1553 } else {
1554 PushWord(X, true);
1555 }
1556 break;
1557 }
1558 case 0xdb: { // stp imp
1559 stopped_ = true;
1560 callbacks_.idle(false);
1561 callbacks_.idle(false);
1562 break;
1563 }
1564 case 0xdc: { // jml ial
1565 uint16_t adr = ReadOpcodeWord(false);
1566 PC = ReadWord(adr, ((adr + 1) & 0xffff), false);
1567 CheckInt();
1568 PB = ReadByte((adr + 2) & 0xffff);
1569 break;
1570 }
1571 case 0xdd: { // cmp abx(r)
1572 uint32_t low = 0;
1573 uint32_t high = AdrAbx(&low, false);
1574 Cmp(low, high);
1575 break;
1576 }
1577 case 0xde: { // dec abx
1578 uint32_t low = 0;
1579 uint32_t high = AdrAbx(&low, true);
1580 Dec(low, high);
1581 break;
1582 }
1583 case 0xdf: { // cmp alx
1584 uint32_t low = 0;
1585 uint32_t high = AdrAlx(&low);
1586 Cmp(low, high);
1587 break;
1588 }
1589 case 0xe0: { // cpx imm(x)
1590 uint32_t low = 0;
1591 uint32_t high = Immediate(&low, true);
1592 Cpx(low, high);
1593 break;
1594 }
1595 case 0xe1: { // sbc idx
1596 uint32_t low = 0;
1597 uint32_t high = AdrIdx(&low);
1598 Sbc(low, high);
1599 break;
1600 }
1601 case 0xe2: { // sep imm(s)
1602 uint8_t val = ReadOpcode();
1603 CheckInt();
1604 SetFlags(status | val);
1605 callbacks_.idle(false);
1606 break;
1607 }
1608 case 0xe3: { // sbc sr
1609 uint32_t low = 0;
1610 uint32_t high = AdrSr(&low);
1611 Sbc(low, high);
1612 break;
1613 }
1614 case 0xe4: { // cpx dp
1615 uint32_t low = 0;
1616 uint32_t high = AdrDp(&low);
1617 Cpx(low, high);
1618 break;
1619 }
1620 case 0xe5: { // sbc dp
1621 uint32_t low = 0;
1622 uint32_t high = AdrDp(&low);
1623 Sbc(low, high);
1624 break;
1625 }
1626 case 0xe6: { // inc dp
1627 uint32_t low = 0;
1628 uint32_t high = AdrDp(&low);
1629 Inc(low, high);
1630 break;
1631 }
1632 case 0xe7: { // sbc idl
1633 uint32_t low = 0;
1634 uint32_t high = AdrIdl(&low);
1635 Sbc(low, high);
1636 break;
1637 }
1638 case 0xe8: { // inx imp
1639 AdrImp();
1640 if (GetIndexSize()) {
1641 X = (X + 1) & 0xff;
1642 } else {
1643 X++;
1644 }
1645 SetZN(X, GetIndexSize());
1646 break;
1647 }
1648 case 0xe9: { // sbc imm(m)
1649 uint32_t low = 0;
1650 uint32_t high = Immediate(&low, false);
1651 Sbc(low, high);
1652 break;
1653 }
1654 case 0xea: { // nop imp
1655 AdrImp();
1656 // no operation
1657 break;
1658 }
1659 case 0xeb: { // xba imp
1660 uint8_t low = A & 0xff;
1661 uint8_t high = A >> 8;
1662 A = (low << 8) | high;
1663 SetZN(high, true);
1664 callbacks_.idle(false);
1665 CheckInt();
1666 callbacks_.idle(false);
1667 break;
1668 }
1669 case 0xec: { // cpx abs
1670 uint32_t low = 0;
1671 uint32_t high = Absolute(&low);
1672 Cpx(low, high);
1673 break;
1674 }
1675 case 0xed: { // sbc abs
1676 uint32_t low = 0;
1677 uint32_t high = Absolute(&low);
1678 Sbc(low, high);
1679 break;
1680 }
1681 case 0xee: { // inc abs
1682 uint32_t low = 0;
1683 uint32_t high = Absolute(&low);
1684 Inc(low, high);
1685 break;
1686 }
1687 case 0xef: { // sbc abl
1688 uint32_t low = 0;
1689 uint32_t high = AdrAbl(&low);
1690 Sbc(low, high);
1691 break;
1692 }
1693 case 0xf0: { // beq rel
1695 break;
1696 }
1697 case 0xf1: { // sbc idy(r)
1698 uint32_t low = 0;
1699 uint32_t high = AdrIdy(&low, false);
1700 Sbc(low, high);
1701 break;
1702 }
1703 case 0xf2: { // sbc idp
1704 uint32_t low = 0;
1705 uint32_t high = AdrIdp(&low);
1706 Sbc(low, high);
1707 break;
1708 }
1709 case 0xf3: { // sbc isy
1710 uint32_t low = 0;
1711 uint32_t high = AdrIsy(&low);
1712 Sbc(low, high);
1713 break;
1714 }
1715 case 0xf4: { // pea imm(l)
1716 PushWord(ReadOpcodeWord(false), true);
1717 break;
1718 }
1719 case 0xf5: { // sbc dpx
1720 uint32_t low = 0;
1721 uint32_t high = AdrDpx(&low);
1722 Sbc(low, high);
1723 break;
1724 }
1725 case 0xf6: { // inc dpx
1726 uint32_t low = 0;
1727 uint32_t high = AdrDpx(&low);
1728 Inc(low, high);
1729 break;
1730 }
1731 case 0xf7: { // sbc ily
1732 uint32_t low = 0;
1733 uint32_t high = AdrIly(&low);
1734 Sbc(low, high);
1735 break;
1736 }
1737 case 0xf8: { // sed imp
1738 AdrImp();
1739 SetDecimalFlag(true);
1740 break;
1741 }
1742 case 0xf9: { // sbc aby(r)
1743 uint32_t low = 0;
1744 uint32_t high = AdrAby(&low, false);
1745 Sbc(low, high);
1746 break;
1747 }
1748 case 0xfa: { // plx imp
1749 callbacks_.idle(false);
1750 callbacks_.idle(false);
1751 if (GetIndexSize()) {
1752 CheckInt();
1753 X = PopByte();
1754 } else {
1755 X = PopWord(true);
1756 }
1757 SetZN(X, GetIndexSize());
1758 break;
1759 }
1760 case 0xfb: { // xce imp
1761 AdrImp();
1762 bool temp = GetCarryFlag();
1763 SetCarryFlag(E);
1764 E = temp;
1765 SetFlags(status); // updates x and m flags, clears upper half of x and y
1766 // if needed
1767 break;
1768 }
1769 case 0xfc: { // jsr iax
1770 uint8_t adrl = ReadOpcode();
1771 PushWord(PC, false);
1772 uint16_t adr = adrl | (ReadOpcode() << 8);
1773 callbacks_.idle(false);
1774 uint16_t value = ReadWord((PB << 16) | ((adr + X) & 0xffff),
1775 (PB << 16) | ((adr + X + 1) & 0xffff), true);
1776 PC = value;
1777 break;
1778 }
1779 case 0xfd: { // sbc abx(r)
1780 uint32_t low = 0;
1781 uint32_t high = AdrAbx(&low, false);
1782 Sbc(low, high);
1783 break;
1784 }
1785 case 0xfe: { // inc abx
1786 uint32_t low = 0;
1787 uint32_t high = AdrAbx(&low, true);
1788 Inc(low, high);
1789 break;
1790 }
1791 case 0xff: { // sbc alx
1792 uint32_t low = 0;
1793 uint32_t high = AdrAlx(&low);
1794 Sbc(low, high);
1795 break;
1796 }
1797 }
1798 if (log_instructions_) {
1799 LogInstructions(cache_pc, opcode, operand, immediate, accumulator_mode);
1800 }
1801 // instruction_length = GetInstructionLength(opcode);
1802 // UpdatePC(instruction_length);
1803}
1804
1805void Cpu::LogInstructions(uint16_t PC, uint8_t opcode, uint16_t operand,
1806 bool immediate, bool accumulator_mode) {
1807 if (flags()->kLogInstructions) {
1808 std::ostringstream oss;
1809 oss << "$" << std::uppercase << std::setw(2) << std::setfill('0')
1810 << static_cast<int>(PB) << ":" << std::hex << PC << ": 0x"
1811 << std::setw(2) << std::setfill('0') << std::hex
1812 << static_cast<int>(opcode) << " " << opcode_to_mnemonic.at(opcode)
1813 << " ";
1814
1815 // Log the operand.
1816 std::string ops;
1817 if (operand) {
1818 if (immediate) {
1819 ops += "#";
1820 }
1821 std::ostringstream oss_ops;
1822 oss_ops << "$";
1823 if (accumulator_mode) {
1824 oss_ops << std::hex << std::setw(2) << std::setfill('0')
1825 << static_cast<int>(operand);
1826 } else {
1827 oss_ops << std::hex << std::setw(4) << std::setfill('0')
1828 << static_cast<int>(operand);
1829 }
1830 ops = oss_ops.str();
1831 }
1832
1833 oss << ops << std::endl;
1834
1835 InstructionEntry entry(PC, opcode, ops, oss.str());
1836 instruction_log_.push_back(entry);
1837 } else {
1838 // Log the address and opcode.
1839 std::cout << "\033[1;36m"
1840 << "$" << std::uppercase << std::setw(2) << std::setfill('0')
1841 << static_cast<int>(PB) << ":" << std::hex << PC;
1842 std::cout << " \033[1;32m"
1843 << ": 0x" << std::hex << std::uppercase << std::setw(2)
1844 << std::setfill('0') << static_cast<int>(opcode) << " ";
1845 std::cout << " \033[1;35m" << opcode_to_mnemonic.at(opcode) << " "
1846 << "\033[0m";
1847
1848 // Log the operand.
1849 if (operand) {
1850 if (immediate) {
1851 std::cout << "#";
1852 }
1853 std::cout << "$";
1854 if (accumulator_mode) {
1855 std::cout << std::hex << std::setw(2) << std::setfill('0') << operand;
1856 } else {
1857 std::cout << std::hex << std::setw(4) << std::setfill('0')
1858 << static_cast<int>(operand);
1859 }
1860
1861 bool x_indexing, y_indexing;
1862 auto x_indexed_instruction_opcodes = {0x15, 0x16, 0x17, 0x55, 0x56,
1863 0x57, 0xD5, 0xD6, 0xD7, 0xF5,
1864 0xF6, 0xF7, 0xBD};
1865 auto y_indexed_instruction_opcodes = {0x19, 0x97, 0x1D, 0x59, 0x5D, 0x99,
1866 0x9D, 0xB9, 0xD9, 0xDD, 0xF9, 0xFD};
1867 if (std::find(x_indexed_instruction_opcodes.begin(),
1868 x_indexed_instruction_opcodes.end(),
1869 opcode) != x_indexed_instruction_opcodes.end()) {
1870 x_indexing = true;
1871 } else {
1872 x_indexing = false;
1873 }
1874 if (std::find(y_indexed_instruction_opcodes.begin(),
1875 y_indexed_instruction_opcodes.end(),
1876 opcode) != y_indexed_instruction_opcodes.end()) {
1877 y_indexing = true;
1878 } else {
1879 y_indexing = false;
1880 }
1881
1882 if (x_indexing) {
1883 std::cout << ", X";
1884 }
1885
1886 if (y_indexing) {
1887 std::cout << ", Y";
1888 }
1889 }
1890
1891 // Log the registers and flags.
1892 std::cout << std::right;
1893 std::cout << "\033[1;33m"
1894 << " A:" << std::hex << std::setw(2) << std::setfill('0')
1895 << static_cast<int>(A);
1896 std::cout << " X:" << std::hex << std::setw(2) << std::setfill('0')
1897 << static_cast<int>(X);
1898 std::cout << " Y:" << std::hex << std::setw(2) << std::setfill('0')
1899 << static_cast<int>(Y);
1900 std::cout << " S:" << std::hex << std::setw(2) << std::setfill('0')
1901 << static_cast<int>(status);
1902 std::cout << " DB:" << std::hex << std::setw(2) << std::setfill('0')
1903 << static_cast<int>(DB);
1904 std::cout << " D:" << std::hex << std::setw(2) << std::setfill('0')
1905 << static_cast<int>(D);
1906 std::cout << " SP:" << std::hex << std::setw(4) << std::setfill('0')
1907 << SP();
1908
1909 std::cout << std::endl;
1910 }
1911}
2262} // namespace emu
2263} // namespace app
2264} // namespace yaze
uint16_t D
Definition cpu.h:80
bool GetOverflowFlag() const
Definition cpu.h:141
uint8_t E
Definition cpu.h:84
void SetZeroFlag(bool set)
Definition cpu.h:136
uint16_t ReadOpcodeWord(bool int_check=false)
Definition cpu.h:152
void Lsr(uint32_t low, uint32_t high)
void Dec(uint32_t low, uint32_t high)
uint32_t AdrAbx(uint32_t *low, bool write)
bool GetNegativeFlag() const
Definition cpu.h:140
void Adc(uint32_t low, uint32_t high)
void SetZN(uint16_t value, bool byte)
Definition cpu.h:112
uint32_t AdrIsy(uint32_t *low)
Definition addressing.cc:89
uint32_t AdrIdl(uint32_t *low)
Definition addressing.cc:64
void SetCarryFlag(bool set)
Definition cpu.h:137
uint16_t SP() const
Definition cpu.h:730
uint16_t ReadWord(uint32_t address, uint32_t address_high, bool int_check=false)
Definition cpu.h:160
void LogInstructions(uint16_t PC, uint8_t opcode, uint16_t operand, bool immediate, bool accumulator_mode)
Definition cpu.cc:1805
void SetDecimalFlag(bool set)
Definition cpu.h:134
void SetSP(uint16_t value)
Definition cpu.h:731
void Sbc(uint32_t low, uint32_t high)
uint32_t AdrSr(uint32_t *low)
Definition addressing.cc:82
void Ror(uint32_t low, uint32_t high)
void Bit(uint32_t low, uint32_t high)
int GetAccumulatorSize() const
Definition cpu.h:125
memory::CpuCallbacks callbacks_
Definition cpu.h:796
void DoBranch(bool check)
Definition cpu.h:227
uint8_t PB
Definition cpu.h:82
int GetIndexSize() const
Definition cpu.h:126
uint32_t AdrIdy(uint32_t *low, bool write)
Definition addressing.cc:53
uint16_t PC
Definition cpu.h:83
uint32_t AdrAby(uint32_t *low, bool write)
uint16_t Y
Definition cpu.h:79
void Reset(bool hard=false)
Definition cpu.cc:15
void CheckInt()
Definition cpu.h:749
void Cpy(uint32_t low, uint32_t high)
void PushWord(uint16_t value, bool int_check=false)
Definition cpu.h:201
uint32_t AdrDpx(uint32_t *low)
Definition addressing.cc:29
void ORA(uint32_t low, uint32_t high)
bool GetZeroFlag() const
Definition cpu.h:145
uint8_t status
Definition cpu.h:85
uint8_t DB
Definition cpu.h:81
uint32_t Immediate(uint32_t *low, bool xFlag)
Definition addressing.cc:19
void DoInterrupt()
Definition cpu.cc:87
void SetFlags(uint8_t val)
Definition cpu.h:99
uint32_t AdrAlx(uint32_t *low)
uint16_t A
Definition cpu.h:77
uint32_t AdrDpy(uint32_t *low)
Definition addressing.cc:37
uint16_t X
Definition cpu.h:78
uint32_t AdrIdx(uint32_t *low)
void Inc(uint32_t low, uint32_t high)
uint8_t ReadByte(uint32_t address)
Definition cpu.h:159
void Asl(uint32_t low, uint32_t high)
void Tsb(uint32_t low, uint32_t high)
uint8_t ReadOpcode()
Definition cpu.h:150
void Cpx(uint32_t low, uint32_t high)
void SetOverflowFlag(bool set)
Definition cpu.h:132
uint16_t PopWord(bool int_check=false)
Definition cpu.h:216
bool GetCarryFlag() const
Definition cpu.h:146
void And(uint32_t low, uint32_t high)
void Sty(uint32_t low, uint32_t high)
bool reset_wanted_
Definition cpu.h:792
void Ldy(uint32_t low, uint32_t high)
void Cmp(uint32_t low, uint32_t high)
uint32_t AdrIly(uint32_t *low)
Definition addressing.cc:73
void Sta(uint32_t low, uint32_t high)
void WriteByte(uint32_t address, uint8_t value)
Definition cpu.h:174
void RunOpcode()
Definition cpu.cc:37
uint32_t AdrAbl(uint32_t *low)
uint32_t Absolute(uint32_t *low)
Definition addressing.cc:98
void Ldx(uint32_t low, uint32_t high)
void SetInterruptFlag(bool set)
Definition cpu.h:135
std::vector< InstructionEntry > instruction_log_
Definition cpu.h:60
bool log_instructions_
Definition cpu.h:785
void PushByte(uint8_t value)
Definition cpu.h:196
uint32_t AdrIdp(uint32_t *low)
Definition addressing.cc:45
uint8_t PopByte()
Definition cpu.h:211
void Trb(uint32_t low, uint32_t high)
void ExecuteInstruction(uint8_t opcode)
Definition cpu.cc:104
void Stz(uint32_t low, uint32_t high)
void Lda(uint32_t low, uint32_t high)
void Eor(uint32_t low, uint32_t high)
void Rol(uint32_t low, uint32_t high)
uint32_t AdrDp(uint32_t *low)
void Stx(uint32_t low, uint32_t high)
const std::unordered_map< uint8_t, std::string > opcode_to_mnemonic
Definition opcodes.h:7
Definition common.cc:22
std::function< void(bool waiting)> idle
Definition memory.h:37