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