yaze 0.2.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
spc700.cc
Go to the documentation of this file.
2
3#include <iomanip>
4#include <iostream>
5#include <sstream>
6#include <string>
7
9
10namespace yaze {
11namespace emu {
12
13void Spc700::Reset(bool hard) {
14 if (hard) {
15 PC = 0;
16 A = 0;
17 X = 0;
18 Y = 0;
19 SP = 0x00;
20 PSW = ByteToFlags(0x00);
21 }
22 step = 0;
23 stopped_ = false;
24 reset_wanted_ = true;
25}
26
28 if (reset_wanted_) {
29 // based on 6502, brk without writes
30 reset_wanted_ = false;
31 read(PC);
32 read(PC);
33 read(0x100 | SP--);
34 read(0x100 | SP--);
35 read(0x100 | SP--);
36 callbacks_.idle(false);
37 PSW.I = false;
38 PC = read_word(0xfffe);
39 return;
40 }
41 if (stopped_) {
42 callbacks_.idle(true);
43 return;
44 }
45 if (step == 0) {
46 bstep = 0;
48 step = 1;
49 return;
50 }
52 if (step == 1) step = 0; // reset step for non cycle-stepped opcodes.
53}
54
56 switch (opcode) {
57 case 0x00: { // nop imp
58 read(PC);
59 // no operation
60 break;
61 }
62 case 0x01:
63 case 0x11:
64 case 0x21:
65 case 0x31:
66 case 0x41:
67 case 0x51:
68 case 0x61:
69 case 0x71:
70 case 0x81:
71 case 0x91:
72 case 0xa1:
73 case 0xb1:
74 case 0xc1:
75 case 0xd1:
76 case 0xe1:
77 case 0xf1: { // tcall imp
78 read(PC);
79 callbacks_.idle(false);
81 callbacks_.idle(false);
82 uint16_t adr = 0xffde - (2 * (opcode >> 4));
83 PC = read_word(adr);
84 break;
85 }
86 case 0x02:
87 case 0x22:
88 case 0x42:
89 case 0x62:
90 case 0x82:
91 case 0xa2:
92 case 0xc2:
93 case 0xe2: { // set1 dp
94 uint16_t adr = dp();
95 write(adr, read(adr) | (1 << (opcode >> 5)));
96 break;
97 }
98 case 0x12:
99 case 0x32:
100 case 0x52:
101 case 0x72:
102 case 0x92:
103 case 0xb2:
104 case 0xd2:
105 case 0xf2: { // clr1 dp
106 uint16_t adr = dp();
107 write(adr, read(adr) & ~(1 << (opcode >> 5)));
108 break;
109 }
110 case 0x03:
111 case 0x23:
112 case 0x43:
113 case 0x63:
114 case 0x83:
115 case 0xa3:
116 case 0xc3:
117 case 0xe3: { // bbs dp, rel
118 uint8_t val = read(dp());
119 callbacks_.idle(false);
120 DoBranch(ReadOpcode(), val & (1 << (opcode >> 5)));
121 break;
122 }
123 case 0x13:
124 case 0x33:
125 case 0x53:
126 case 0x73:
127 case 0x93:
128 case 0xb3:
129 case 0xd3:
130 case 0xf3: { // bbc dp, rel
131 uint8_t val = read(dp());
132 callbacks_.idle(false);
133 DoBranch(ReadOpcode(), (val & (1 << (opcode >> 5))) == 0);
134 break;
135 }
136
137 case 0x04: { // or dp
138 OR(dp());
139 break;
140 }
141 case 0x05: { // or abs
142 OR(abs());
143 break;
144 }
145 case 0x06: { // or ind
146 OR(ind());
147 break;
148 }
149 case 0x07: { // or idx
150 OR(idx());
151 break;
152 }
153 case 0x08: { // or imm
154 OR(imm());
155 break;
156 }
157 case 0x09: { // orm dp, dp
158 uint8_t src = 0;
159 uint16_t dst = dp_dp(&src);
160 ORM(dst, src);
161 break;
162 }
163 case 0x0a: { // or1 abs.bit
164 uint16_t adr = 0;
165 uint8_t bit = abs_bit(&adr);
166 PSW.C = PSW.C | ((read(adr) >> bit) & 1);
167 callbacks_.idle(false);
168 break;
169 }
170 case 0x0b: { // asl dp
171 ASL(dp());
172 break;
173 }
174 case 0x0c: { // asl abs
175 ASL(abs());
176 break;
177 }
178 case 0x0d: { // pushp imp
179 read(PC);
181 callbacks_.idle(false);
182 break;
183 }
184 case 0x0e: { // tset1 abs
185 uint16_t adr = abs();
186 uint8_t val = read(adr);
187 read(adr);
188 uint8_t result = A + (val ^ 0xff) + 1;
189 PSW.Z = (result == 0);
190 PSW.N = (result & 0x80);
191 write(adr, val | A);
192 break;
193 }
194 case 0x0f: { // brk imp
195 read(PC);
196 push_word(PC);
198 callbacks_.idle(false);
199 PSW.I = false;
200 PSW.B = true;
201 PC = read_word(0xffde);
202 break;
203 }
204 case 0x10: { // bpl rel
205 DoBranch(ReadOpcode(), !PSW.N);
206 break;
207 }
208 case 0x14: { // or dpx
209 OR(dpx());
210 break;
211 }
212 case 0x15: { // or abx
213 OR(abs_x());
214 break;
215 }
216 case 0x16: { // or aby
217 OR(abs_y());
218 break;
219 }
220 case 0x17: { // or idy
221 OR(idy());
222 break;
223 }
224 case 0x18: { // orm dp, imm
225 uint8_t src = 0;
226 uint16_t dst = dp_imm(&src);
227 ORM(dst, src);
228 break;
229 }
230 case 0x19: { // orm ind, ind
231 uint8_t src = 0;
232 uint16_t dst = ind_ind(&src);
233 ORM(dst, src);
234 break;
235 }
236 case 0x1a: { // decw dp
237 uint16_t low = 0;
238 uint16_t high = dp_word(&low);
239 uint16_t value = read(low) - 1;
240 write(low, value & 0xff);
241 value += read(high) << 8;
242 write(high, value >> 8);
243 PSW.Z = value == 0;
244 PSW.N = value & 0x8000;
245 break;
246 }
247 case 0x1b: { // asl dpx
248 ASL(dpx());
249 break;
250 }
251 case 0x1c: { // asla imp
252 read(PC);
253 PSW.C = A & 0x80;
254 A <<= 1;
255 PSW.Z = (A == 0);
256 PSW.N = (A & 0x80);
257 break;
258 }
259 case 0x1d: { // decx imp
260 read(PC);
261 X--;
262 PSW.Z = (X == 0);
263 PSW.N = (X & 0x80);
264 break;
265 }
266 case 0x1e: { // cmpx abs
267 CMPX(abs());
268 break;
269 }
270 case 0x1f: { // jmp iax
271 uint16_t pointer = ReadOpcodeWord();
272 callbacks_.idle(false);
273 PC = read_word((pointer + X) & 0xffff);
274 break;
275 }
276 case 0x20: { // clrp imp
277 read(PC);
278 PSW.P = false;
279 break;
280 }
281 case 0x24: { // and dp
282 AND(dp());
283 break;
284 }
285 case 0x25: { // and abs
286 AND(abs());
287 break;
288 }
289 case 0x26: { // and ind
290 AND(ind());
291 break;
292 }
293 case 0x27: { // and idx
294 AND(idx());
295 break;
296 }
297 case 0x28: { // and imm
298 AND(imm());
299 break;
300 }
301 case 0x29: { // andm dp, dp
302 uint8_t src = 0;
303 uint16_t dst = dp_dp(&src);
304 ANDM(dst, src);
305 break;
306 }
307 case 0x2a: { // or1n abs.bit
308 uint16_t adr = 0;
309 uint8_t bit = abs_bit(&adr);
310 PSW.C = PSW.C | (~(read(adr) >> bit) & 1);
311 callbacks_.idle(false);
312 break;
313 }
314 case 0x2b: { // rol dp
315 ROL(dp());
316 break;
317 }
318 case 0x2c: { // rol abs
319 ROL(abs());
320 break;
321 }
322 case 0x2d: { // pusha imp
323 read(PC);
324 push_byte(A);
325 callbacks_.idle(false);
326 break;
327 }
328 case 0x2e: { // cbne dp, rel
329 uint8_t val = read(dp()) ^ 0xff;
330 callbacks_.idle(false);
331 uint8_t result = A + val + 1;
332 DoBranch(ReadOpcode(), result != 0);
333 break;
334 }
335 case 0x2f: { // bra rel
336 DoBranch(ReadOpcode(), true);
337 break;
338 }
339 case 0x30: { // bmi rel
340 DoBranch(ReadOpcode(), PSW.N);
341 break;
342 }
343 case 0x34: { // and dpx
344 AND(dpx());
345 break;
346 }
347 case 0x35: { // and abx
348 AND(abs_x());
349 break;
350 }
351 case 0x36: { // and aby
352 AND(abs_y());
353 break;
354 }
355 case 0x37: { // and idy
356 AND(idy());
357 break;
358 }
359 case 0x38: { // andm dp, imm
360 uint8_t src = 0;
361 uint16_t dst = dp_imm(&src);
362 ANDM(dst, src);
363 break;
364 }
365 case 0x39: { // andm ind, ind
366 uint8_t src = 0;
367 uint16_t dst = ind_ind(&src);
368 ANDM(dst, src);
369 break;
370 }
371 case 0x3a: { // incw dp
372 uint16_t low = 0;
373 uint16_t high = dp_word(&low);
374 uint16_t value = read(low) + 1;
375 write(low, value & 0xff);
376 value += read(high) << 8;
377 write(high, value >> 8);
378 PSW.Z = value == 0;
379 PSW.N = value & 0x8000;
380 break;
381 }
382 case 0x3b: { // rol dpx
383 ROL(dpx());
384 break;
385 }
386 case 0x3c: { // rola imp
387 read(PC);
388 bool newC = A & 0x80;
389 A = (A << 1) | PSW.C;
390 PSW.C = newC;
391 PSW.Z = (A == 0);
392 PSW.N = (A & 0x80);
393 break;
394 }
395 case 0x3d: { // incx imp
396 read(PC);
397 X++;
398 PSW.Z = (X == 0);
399 PSW.N = (X & 0x80);
400 break;
401 }
402 case 0x3e: { // cmpx dp
403 CMPX(dp());
404 break;
405 }
406 case 0x3f: { // call abs
407 uint16_t dst = ReadOpcodeWord();
408 callbacks_.idle(false);
409 push_word(PC);
410 callbacks_.idle(false);
411 callbacks_.idle(false);
412 PC = dst;
413 break;
414 }
415 case 0x40: { // setp imp
416 read(PC);
417 PSW.P = true;
418 break;
419 }
420 case 0x44: { // eor dp
421 EOR(dp());
422 break;
423 }
424 case 0x45: { // eor abs
425 EOR(abs());
426 break;
427 }
428 case 0x46: { // eor ind
429 EOR(ind());
430 break;
431 }
432 case 0x47: { // eor idx
433 EOR(idx());
434 break;
435 }
436 case 0x48: { // eor imm
437 EOR(imm());
438 break;
439 }
440 case 0x49: { // eorm dp, dp
441 uint8_t src = 0;
442 uint16_t dst = dp_dp(&src);
443 EORM(dst, src);
444 break;
445 }
446 case 0x4a: { // and1 abs.bit
447 uint16_t adr = 0;
448 uint8_t bit = abs_bit(&adr);
449 PSW.C = PSW.C & ((read(adr) >> bit) & 1);
450 break;
451 }
452 case 0x4b: { // lsr dp
453 LSR(dp());
454 break;
455 }
456 case 0x4c: { // lsr abs
457 LSR(abs());
458 break;
459 }
460 case 0x4d: { // pushx imp
461 read(PC);
462 push_byte(X);
463 callbacks_.idle(false);
464 break;
465 }
466 case 0x4e: { // tclr1 abs
467 uint16_t adr = abs();
468 uint8_t val = read(adr);
469 read(adr);
470 uint8_t result = A + (val ^ 0xff) + 1;
471 PSW.Z = (result == 0);
472 PSW.N = (result & 0x80);
473 write(adr, val & ~A);
474 break;
475 }
476 case 0x4f: { // pcall dp
477 uint8_t dst = ReadOpcode();
478 callbacks_.idle(false);
479 push_word(PC);
480 callbacks_.idle(false);
481 PC = 0xff00 | dst;
482 break;
483 }
484 case 0x50: { // bvc rel
485 DoBranch(ReadOpcode(), !PSW.V);
486 break;
487 }
488 case 0x54: { // eor dpx
489 EOR(dpx());
490 break;
491 }
492 case 0x55: { // eor abx
493 EOR(abs_x());
494 break;
495 }
496 case 0x56: { // eor aby
497 EOR(abs_y());
498 break;
499 }
500 case 0x57: { // eor idy
501 EOR(idy());
502 break;
503 }
504 case 0x58: { // eorm dp, imm
505 uint8_t src = 0;
506 uint16_t dst = dp_imm(&src);
507 EORM(dst, src);
508 break;
509 }
510 case 0x59: { // eorm ind, ind
511 uint8_t src = 0;
512 uint16_t dst = ind_ind(&src);
513 EORM(dst, src);
514 break;
515 }
516 case 0x5a: { // cmpw dp
517 uint16_t low = 0;
518 // uint16_t high = dp_word(&low);
519 uint16_t value = read_word(low) ^ 0xffff;
520 uint16_t ya = A | (Y << 8);
521 int result = ya + value + 1;
522 PSW.C = result > 0xffff;
523 PSW.Z = (result & 0xffff) == 0;
524 PSW.N = result & 0x8000;
525 break;
526 }
527 case 0x5b: { // lsr dpx
528 LSR(dpx());
529 break;
530 }
531 case 0x5c: { // lsra imp
532 read(PC);
533 PSW.C = A & 1;
534 A >>= 1;
535 PSW.Z = (A == 0);
536 PSW.N = (A & 0x80);
537 break;
538 }
539 case 0x5d: { // movxa imp
540 read(PC);
541 X = A;
542 PSW.Z = (X == 0);
543 PSW.N = (X & 0x80);
544 break;
545 }
546 case 0x5e: { // cmpy abs
547 CMPY(abs());
548 break;
549 }
550 case 0x5f: { // jmp abs
551 PC = ReadOpcodeWord();
552 break;
553 }
554 case 0x60: { // clrc imp
555 read(PC);
556 PSW.C = false;
557 break;
558 }
559 case 0x64: { // cmp dp
560 CMP(dp());
561 break;
562 }
563 case 0x65: { // cmp abs
564 CMP(abs());
565 break;
566 }
567 case 0x66: { // cmp ind
568 CMP(ind());
569 break;
570 }
571 case 0x67: { // cmp idx
572 CMP(idx());
573 break;
574 }
575 case 0x68: { // cmp imm
576 CMP(imm());
577 break;
578 }
579 case 0x69: { // cmpm dp, dp
580 uint8_t src = 0;
581 uint16_t dst = dp_dp(&src);
582 CMPM(dst, src);
583 break;
584 }
585 case 0x6a: { // and1n abs.bit
586 uint16_t adr = 0;
587 uint8_t bit = abs_bit(&adr);
588 PSW.C = PSW.C & (~(read(adr) >> bit) & 1);
589 break;
590 }
591 case 0x6b: { // ror dp
592 ROR(dp());
593 break;
594 }
595 case 0x6c: { // ror abs
596 ROR(abs());
597 break;
598 }
599 case 0x6d: { // pushy imp
600 read(PC);
601 push_byte(Y);
602 callbacks_.idle(false);
603 break;
604 }
605 case 0x6e: { // dbnz dp, rel
606 uint16_t adr = dp();
607 uint8_t result = read(adr) - 1;
608 write(adr, result);
609 DoBranch(ReadOpcode(), result != 0);
610 break;
611 }
612 case 0x6f: { // ret imp
613 read(PC);
614 callbacks_.idle(false);
615 PC = pull_word();
616 break;
617 }
618 case 0x70: { // bvs rel
619 DoBranch(ReadOpcode(), PSW.V);
620 break;
621 }
622 case 0x74: { // cmp dpx
623 CMP(dpx());
624 break;
625 }
626 case 0x75: { // cmp abx
627 CMP(abs_x());
628 break;
629 }
630 case 0x76: { // cmp aby
631 CMP(abs_y());
632 break;
633 }
634 case 0x77: { // cmp idy
635 CMP(idy());
636 break;
637 }
638 case 0x78: { // cmpm dp, imm
639 uint8_t src = 0;
640 uint16_t dst = dp_imm(&src);
641 CMPM(dst, src);
642 break;
643 }
644 case 0x79: { // cmpm ind, ind
645 uint8_t src = 0;
646 uint16_t dst = ind_ind(&src);
647 CMPM(dst, src);
648 break;
649 }
650 case 0x7a: { // addw dp
651 uint16_t low = 0;
652 uint16_t high = dp_word(&low);
653 uint8_t vall = read(low);
654 callbacks_.idle(false);
655 uint16_t value = vall | (read(high) << 8);
656 uint16_t ya = A | (Y << 8);
657 int result = ya + value;
658 PSW.V = (ya & 0x8000) == (value & 0x8000) &&
659 (value & 0x8000) != (result & 0x8000);
660 PSW.H = ((ya & 0xfff) + (value & 0xfff)) > 0xfff;
661 PSW.C = result > 0xffff;
662 PSW.Z = (result & 0xffff) == 0;
663 PSW.N = result & 0x8000;
664 A = result & 0xff;
665 Y = result >> 8;
666 break;
667 }
668 case 0x7b: { // ror dpx
669 ROR(dpx());
670 break;
671 }
672 case 0x7c: { // rora imp
673 read(PC);
674 bool newC = A & 1;
675 A = (A >> 1) | (PSW.C << 7);
676 PSW.C = newC;
677 PSW.Z = (A == 0);
678 PSW.N = (A & 0x80);
679 break;
680 }
681 case 0x7d: { // movax imp
682 read(PC);
683 A = X;
684 PSW.Z = (A == 0);
685 PSW.N = (A & 0x80);
686 break;
687 }
688 case 0x7e: { // cmpy dp
689 CMPY(dp());
690 break;
691 }
692 case 0x7f: { // reti imp
693 read(PC);
694 callbacks_.idle(false);
696 PC = pull_word();
697 break;
698 }
699 case 0x80: { // setc imp
700 read(PC);
701 PSW.C = true;
702 break;
703 }
704 case 0x84: { // adc dp
705 ADC(dp());
706 break;
707 }
708 case 0x85: { // adc abs
709 ADC(abs());
710 break;
711 }
712 case 0x86: { // adc ind
713 ADC(ind());
714 break;
715 }
716 case 0x87: { // adc idx
717 ADC(idx());
718 break;
719 }
720 case 0x88: { // adc imm
721 ADC(imm());
722 break;
723 }
724 case 0x89: { // adcm dp, dp
725 uint8_t src = 0;
726 uint16_t dst = dp_dp(&src);
727 ADCM(dst, src);
728 break;
729 }
730 case 0x8a: { // eor1 abs.bit
731 uint16_t adr = 0;
732 uint8_t bit = abs_bit(&adr);
733 PSW.C = PSW.C ^ ((read(adr) >> bit) & 1);
734 callbacks_.idle(false);
735 break;
736 }
737 case 0x8b: { // dec dp
738 DEC(dp());
739 break;
740 }
741 case 0x8c: { // dec abs
742 DEC(abs());
743 break;
744 }
745 case 0x8d: { // movy imm
746 MOVY(imm());
747 break;
748 }
749 case 0x8e: { // popp imp
750 read(PC);
751 callbacks_.idle(false);
753 break;
754 }
755 case 0x8f: { // movm dp, imm
756 uint8_t val = 0;
757 uint16_t dst = dp_imm(&val);
758 read(dst);
759 write(dst, val);
760 break;
761 }
762 case 0x90: { // bcc rel
763 DoBranch(ReadOpcode(), !PSW.C);
764 break;
765 }
766 case 0x94: { // adc dpx
767 ADC(dpx());
768 break;
769 }
770 case 0x95: { // adc abx
771 ADC(abs_x());
772 break;
773 }
774 case 0x96: { // adc aby
775 ADC(abs_y());
776 break;
777 }
778 case 0x97: { // adc idy
779 ADC(idy());
780 break;
781 }
782 case 0x98: { // adcm dp, imm
783 uint8_t src = 0;
784 uint16_t dst = dp_imm(&src);
785 ADCM(dst, src);
786 break;
787 }
788 case 0x99: { // adcm ind, ind
789 uint8_t src = 0;
790 uint16_t dst = ind_ind(&src);
791 ADCM(dst, src);
792 break;
793 }
794 case 0x9a: { // subw dp
795 uint16_t low = 0;
796 uint16_t high = dp_word(&low);
797 uint8_t vall = read(low);
798 callbacks_.idle(false);
799 uint16_t value = (vall | (read(high) << 8)) ^ 0xffff;
800 uint16_t ya = A | (Y << 8);
801 int result = ya + value + 1;
802 PSW.V = (ya & 0x8000) == (value & 0x8000) &&
803 (value & 0x8000) != (result & 0x8000);
804 PSW.H = ((ya & 0xfff) + (value & 0xfff) + 1) > 0xfff;
805 PSW.C = result > 0xffff;
806 PSW.Z = (result & 0xffff) == 0;
807 PSW.N = result & 0x8000;
808 A = result & 0xff;
809 Y = result >> 8;
810 break;
811 }
812 case 0x9b: { // dec dpx
813 DEC(dpx());
814 break;
815 }
816 case 0x9c: { // deca imp
817 read(PC);
818 A--;
819 PSW.Z = (A == 0);
820 PSW.N = (A & 0x80);
821 break;
822 }
823 case 0x9d: { // movxp imp
824 read(PC);
825 X = SP;
826 PSW.Z = (X == 0);
827 PSW.N = (X & 0x80);
828 break;
829 }
830 case 0x9e: { // div imp
831 read(PC);
832 for (int i = 0; i < 10; i++) callbacks_.idle(false);
833 PSW.H = (X & 0xf) <= (Y & 0xf);
834 int yva = (Y << 8) | A;
835 int x = X << 9;
836 for (int i = 0; i < 9; i++) {
837 yva <<= 1;
838 yva |= (yva & 0x20000) ? 1 : 0;
839 yva &= 0x1ffff;
840 if (yva >= x) yva ^= 1;
841 if (yva & 1) yva -= x;
842 yva &= 0x1ffff;
843 }
844 Y = yva >> 9;
845 PSW.V = yva & 0x100;
846 A = yva & 0xff;
847 PSW.Z = (A == 0);
848 PSW.N = (A & 0x80);
849 break;
850 }
851 case 0x9f: { // xcn imp
852 read(PC);
853 callbacks_.idle(false);
854 callbacks_.idle(false);
855 callbacks_.idle(false);
856 A = (A >> 4) | (A << 4);
857 PSW.Z = (A == 0);
858 PSW.N = (A & 0x80);
859 break;
860 }
861 case 0xa0: { // ei imp
862 read(PC);
863 callbacks_.idle(false);
864 PSW.I = true;
865 break;
866 }
867 case 0xa4: { // sbc dp
868 SBC(dp());
869 break;
870 }
871 case 0xa5: { // sbc abs
872 SBC(abs());
873 break;
874 }
875 case 0xa6: { // sbc ind
876 SBC(ind());
877 break;
878 }
879 case 0xa7: { // sbc idx
880 SBC(idx());
881 break;
882 }
883 case 0xa8: { // sbc imm
884 SBC(imm());
885 break;
886 }
887 case 0xa9: { // sbcm dp, dp
888 uint8_t src = 0;
889 uint16_t dst = dp_dp(&src);
890 SBCM(dst, src);
891 break;
892 }
893 case 0xaa: { // mov1 abs.bit
894 uint16_t adr = 0;
895 uint8_t bit = abs_bit(&adr);
896 PSW.C = (read(adr) >> bit) & 1;
897 break;
898 }
899 case 0xab: { // inc dp
900 INC(dp());
901 break;
902 }
903 case 0xac: { // inc abs
904 INC(abs());
905 break;
906 }
907 case 0xad: { // cmpy imm
908 CMPY(imm());
909 break;
910 }
911 case 0xae: { // popa imp
912 read(PC);
913 callbacks_.idle(false);
914 A = pull_byte();
915 break;
916 }
917 case 0xaf: { // movs ind+
918 uint16_t adr = ind_p();
919 callbacks_.idle(false);
920 write(adr, A);
921 break;
922 }
923 case 0xb0: { // bcs rel
924 DoBranch(ReadOpcode(), PSW.C);
925 break;
926 }
927 case 0xb4: { // sbc dpx
928 SBC(dpx());
929 break;
930 }
931 case 0xb5: { // sbc abx
932 SBC(abs_x());
933 break;
934 }
935 case 0xb6: { // sbc aby
936 SBC(abs_y());
937 break;
938 }
939 case 0xb7: { // sbc idy
940 SBC(idy());
941 break;
942 }
943 case 0xb8: { // sbcm dp, imm
944 uint8_t src = 0;
945 uint16_t dst = dp_imm(&src);
946 SBCM(dst, src);
947 break;
948 }
949 case 0xb9: { // sbcm ind, ind
950 uint8_t src = 0;
951 uint16_t dst = ind_ind(&src);
952 SBCM(dst, src);
953 break;
954 }
955 case 0xba: { // movw dp
956 uint16_t low = 0;
957 uint16_t high = dp_word(&low);
958 uint8_t vall = read(low);
959 callbacks_.idle(false);
960 uint16_t val = vall | (read(high) << 8);
961 A = val & 0xff;
962 Y = val >> 8;
963 PSW.Z = val == 0;
964 PSW.N = val & 0x8000;
965 break;
966 }
967 case 0xbb: { // inc dpx
968 INC(dpx());
969 break;
970 }
971 case 0xbc: { // inca imp
972 read(PC);
973 A++;
974 PSW.Z = (A == 0);
975 PSW.N = (A & 0x80);
976 ;
977 break;
978 }
979 case 0xbd: { // movpx imp
980 read(PC);
981 SP = X;
982 break;
983 }
984 case 0xbe: { // das imp
985 read(PC);
986 callbacks_.idle(false);
987 if (A > 0x99 || !PSW.C) {
988 A -= 0x60;
989 PSW.C = false;
990 }
991 if ((A & 0xf) > 9 || !PSW.H) {
992 A -= 6;
993 }
994 PSW.Z = (A == 0);
995 PSW.N = (A & 0x80);
996 break;
997 }
998 case 0xbf: { // mov ind+
999 uint16_t adr = ind_p();
1000 A = read(adr);
1001 callbacks_.idle(false);
1002 PSW.Z = (A == 0);
1003 PSW.N = (A & 0x80);
1004 break;
1005 }
1006 case 0xc0: { // di imp
1007 read(PC);
1008 callbacks_.idle(false);
1009 PSW.I = false;
1010 break;
1011 }
1012 case 0xc4: { // movs dp
1013 MOVS(dp());
1014 break;
1015 }
1016 case 0xc5: { // movs abs
1017 MOVS(abs());
1018 break;
1019 }
1020 case 0xc6: { // movs ind
1021 MOVS(ind());
1022 break;
1023 }
1024 case 0xc7: { // movs idx
1025 MOVS(idx());
1026 break;
1027 }
1028 case 0xc8: { // cmpx imm
1029 CMPX(imm());
1030 break;
1031 }
1032 case 0xc9: { // movsx abs
1033 MOVSX(abs());
1034 break;
1035 }
1036 case 0xca: { // mov1s abs.bit
1037 uint16_t adr = 0;
1038 uint8_t bit = abs_bit(&adr);
1039 uint8_t result = (read(adr) & (~(1 << bit))) | (PSW.C << bit);
1040 callbacks_.idle(false);
1041 write(adr, result);
1042 break;
1043 }
1044 case 0xcb: { // movsy dp
1045 MOVSY(dp());
1046 break;
1047 }
1048 case 0xcc: { // movsy abs
1049 MOVSY(abs());
1050 break;
1051 }
1052 case 0xcd: { // movx imm
1053 MOVX(imm());
1054 break;
1055 }
1056 case 0xce: { // popx imp
1057 read(PC);
1058 callbacks_.idle(false);
1059 X = pull_byte();
1060 break;
1061 }
1062 case 0xcf: { // mul imp
1063 read(PC);
1064 for (int i = 0; i < 7; i++) callbacks_.idle(false);
1065 uint16_t result = A * Y;
1066 A = result & 0xff;
1067 Y = result >> 8;
1068 PSW.Z = ((Y & 0xFFFF) == 0);
1069 PSW.N = (Y & 0x8000);
1070 break;
1071 }
1072 case 0xd0: { // bne rel
1073 switch (step++) {
1074 case 1:
1075 dat = ReadOpcode();
1076 if (PSW.Z) step = 0;
1077 break;
1078 case 2:
1079 callbacks_.idle(false);
1080 break;
1081 case 3:
1082 callbacks_.idle(false);
1083 PC += (int8_t)dat;
1084 step = 0;
1085 break;
1086 }
1087 // DoBranch(ReadOpcode(), !PSW.Z);
1088 break;
1089 }
1090 case 0xd4: { // movs dpx
1091 MOVS(dpx());
1092 break;
1093 }
1094 case 0xd5: { // movs abx
1095 MOVS(abs_x());
1096 break;
1097 }
1098 case 0xd6: { // movs aby
1099 MOVS(abs_y());
1100 break;
1101 }
1102 case 0xd7: { // movs idy
1103 MOVS(idy());
1104 break;
1105 }
1106 case 0xd8: { // movsx dp
1107 MOVSX(dp());
1108 break;
1109 }
1110 case 0xd9: { // movsx dpy
1111 MOVSX(dp_y());
1112 break;
1113 }
1114 case 0xda: { // movws dp
1115 uint16_t low = 0;
1116 uint16_t high = dp_word(&low);
1117 read(low);
1118 write(low, A);
1119 write(high, Y);
1120 break;
1121 }
1122 case 0xdb: { // movsy dpx
1123 MOVSY(dpx());
1124 break;
1125 }
1126 case 0xdc: { // decy imp
1127 read(PC);
1128 Y--;
1129 PSW.Z = ((Y & 0xFFFF) == 0);
1130 PSW.N = (Y & 0x8000);
1131 break;
1132 }
1133 case 0xdd: { // movay imp
1134 read(PC);
1135 A = Y;
1136 PSW.Z = (A == 0);
1137 PSW.N = (A & 0x80);
1138 break;
1139 }
1140 case 0xde: { // cbne dpx, rel
1141 uint8_t val = read(dpx()) ^ 0xff;
1142 callbacks_.idle(false);
1143 uint8_t result = A + val + 1;
1144 DoBranch(ReadOpcode(), result != 0);
1145 break;
1146 }
1147 case 0xdf: { // daa imp
1148 read(PC);
1149 callbacks_.idle(false);
1150 if (A > 0x99 || PSW.C) {
1151 A += 0x60;
1152 PSW.C = true;
1153 }
1154 if ((A & 0xf) > 9 || PSW.H) {
1155 A += 6;
1156 }
1157 PSW.Z = (A == 0);
1158 PSW.N = (A & 0x80);
1159 break;
1160 }
1161 case 0xe0: { // clrv imp
1162 read(PC);
1163 PSW.V = false;
1164 PSW.H = false;
1165 break;
1166 }
1167 case 0xe4: { // mov dp
1168 MOV(dp());
1169 break;
1170 }
1171 case 0xe5: { // mov abs
1172 MOV(abs());
1173 break;
1174 }
1175 case 0xe6: { // mov ind
1176 MOV(ind());
1177 break;
1178 }
1179 case 0xe7: { // mov idx
1180 MOV(idx());
1181 break;
1182 }
1183 case 0xe8: { // mov imm
1184 MOV(imm());
1185 break;
1186 }
1187 case 0xe9: { // movx abs
1188 MOVX(abs());
1189 break;
1190 }
1191 case 0xea: { // not1 abs.bit
1192 uint16_t adr = 0;
1193 uint8_t bit = abs_bit(&adr);
1194 uint8_t result = read(adr) ^ (1 << bit);
1195 write(adr, result);
1196 break;
1197 }
1198 case 0xeb: { // movy dp
1199 MOVY(dp());
1200 break;
1201 }
1202 case 0xec: { // movy abs
1203 MOVY(abs());
1204 break;
1205 }
1206 case 0xed: { // notc imp
1207 read(PC);
1208 callbacks_.idle(false);
1209 PSW.C = !PSW.C;
1210 break;
1211 }
1212 case 0xee: { // popy imp
1213 read(PC);
1214 callbacks_.idle(false);
1215 Y = pull_byte();
1216 break;
1217 }
1218 case 0xef: { // sleep imp
1219 read(PC);
1220 callbacks_.idle(false);
1221 stopped_ = true; // no interrupts, so sleeping stops as well
1222 break;
1223 }
1224 case 0xf0: { // beq rel
1225 DoBranch(ReadOpcode(), PSW.Z);
1226 break;
1227 }
1228 case 0xf4: { // mov dpx
1229 MOV(dpx());
1230 break;
1231 }
1232 case 0xf5: { // mov abx
1233 MOV(abs_x());
1234 break;
1235 }
1236 case 0xf6: { // mov aby
1237 MOV(abs_y());
1238 break;
1239 }
1240 case 0xf7: { // mov idy
1241 MOV(idy());
1242 break;
1243 }
1244 case 0xf8: { // movx dp
1245 MOVX(dp());
1246 break;
1247 }
1248 case 0xf9: { // movx dpy
1249 MOVX(dp_y());
1250 break;
1251 }
1252 case 0xfa: { // movm dp, dp
1253 uint8_t val = 0;
1254 uint16_t dst = dp_dp(&val);
1255 write(dst, val);
1256 break;
1257 }
1258 case 0xfb: { // movy dpx
1259 MOVY(dpx());
1260 break;
1261 }
1262 case 0xfc: { // incy imp
1263 read(PC);
1264 Y++;
1265 PSW.Z = ((Y & 0xFFFF) == 0);
1266 PSW.N = (Y & 0x8000);
1267 break;
1268 }
1269 case 0xfd: { // movya imp
1270 read(PC);
1271 Y = A;
1272 PSW.Z = ((Y & 0xFFFF) == 0);
1273 PSW.N = (Y & 0x8000);
1274 break;
1275 }
1276 case 0xfe: { // dbnzy rel
1277 read(PC);
1278 callbacks_.idle(false);
1279 Y--;
1280 DoBranch(ReadOpcode(), Y != 0);
1281 break;
1282 }
1283 case 0xff: { // stop imp
1284 read(PC);
1285 callbacks_.idle(false);
1286 stopped_ = true;
1287 break;
1288 }
1289
1290 default:
1291 throw std::runtime_error("Unknown SPC opcode: " + std::to_string(opcode));
1292 break;
1293 }
1294}
1295
1296void Spc700::LogInstruction(uint16_t initial_pc, uint8_t opcode) {
1297 std::string mnemonic = spc_opcode_map.at(opcode);
1298
1299 std::stringstream log_entry_stream;
1300 log_entry_stream << "\033[1;36m$" << std::hex << std::setw(4)
1301 << std::setfill('0') << initial_pc << "\033[0m";
1302 log_entry_stream << " \033[1;32m" << std::hex << std::setw(2)
1303 << std::setfill('0') << static_cast<int>(opcode) << "\033[0m"
1304 << " \033[1;35m" << std::setw(18) << std::left
1305 << std::setfill(' ') << mnemonic << "\033[0m";
1306
1307 log_entry_stream << " \033[1;33mA: " << std::hex << std::setw(2)
1308 << std::setfill('0') << std::right << static_cast<int>(A)
1309 << "\033[0m";
1310 log_entry_stream << " \033[1;33mX: " << std::hex << std::setw(2)
1311 << std::setfill('0') << std::right << static_cast<int>(X)
1312 << "\033[0m";
1313 log_entry_stream << " \033[1;33mY: " << std::hex << std::setw(2)
1314 << std::setfill('0') << std::right << static_cast<int>(Y)
1315 << "\033[0m";
1316 std::string log_entry = log_entry_stream.str();
1317
1318 std::cerr << log_entry << std::endl;
1319
1320 // Append the log entry to the log
1321 // log_.push_back(log_entry);
1322}
1323
1324} // namespace emu
1325} // namespace yaze
const std::unordered_map< uint8_t, std::string > spc_opcode_map
Definition opcodes.h:7
void CMPM(uint16_t dst, uint8_t value)
void MOVS(uint16_t adr)
uint16_t pull_word()
Definition spc700.h:192
uint8_t read(uint16_t address)
Definition spc700.h:143
void MOVSX(uint16_t adr)
uint16_t ind_p()
Definition addressing.cc:73
uint16_t adr
Definition spc700.h:80
void MOVX(uint16_t adr)
uint16_t dp_y()
Definition addressing.cc:25
uint32_t bstep
Definition spc700.h:79
uint8_t abs_bit(uint16_t *adr)
Definition addressing.cc:61
void SBC(uint16_t adr)
void CMPY(uint16_t adr)
void ANDM(uint16_t dest, uint8_t operand)
uint8_t opcode
Definition spc700.h:77
uint8_t dat
Definition spc700.h:82
void EORM(uint16_t dest, uint8_t operand)
void DEC(uint16_t operand)
uint16_t ind_ind(uint8_t *srcVal)
Definition addressing.cc:55
uint32_t step
Definition spc700.h:78
void MOV(uint16_t adr)
void SBCM(uint16_t &dest, uint8_t operand)
void Reset(bool hard=false)
Definition spc700.cc:13
void LSR(uint16_t adr)
void push_byte(uint8_t value)
Definition spc700.h:177
void CMPX(uint16_t adr)
uint8_t FlagsToByte(Flags flags)
Definition spc700.h:117
bool reset_wanted_
Definition spc700.h:75
void LogInstruction(uint16_t initial_pc, uint8_t opcode)
Definition spc700.cc:1296
uint16_t abs_y()
Definition addressing.cc:37
uint16_t dp_imm(uint8_t *srcVal)
Definition addressing.cc:50
uint16_t ReadOpcodeWord()
Definition spc700.h:157
void CMP(uint16_t adr)
uint16_t dp_dp(uint8_t *src)
void ROL(uint16_t operand)
void write(uint16_t address, uint8_t value)
Definition spc700.h:173
void INC(uint16_t adr)
uint16_t abs_x()
Definition addressing.cc:31
uint16_t dp_word(uint16_t *low)
Definition addressing.cc:67
void push_word(uint16_t value)
Definition spc700.h:182
void ADC(uint16_t adr)
void EOR(uint16_t adr)
void ROR(uint16_t adr)
uint16_t read_word(uint16_t address)
Definition spc700.h:145
void ASL(uint16_t operand)
void OR(uint16_t adr)
void ADCM(uint16_t &dest, uint8_t operand)
void DoBranch(uint8_t value, bool check)
Definition spc700.h:163
uint16_t PC
Definition spc700.h:102
void AND(uint16_t adr)
uint8_t pull_byte()
Definition spc700.h:187
ApuCallbacks callbacks_
Definition spc700.h:71
void MOVSY(uint16_t adr)
void ExecuteInstructions(uint8_t opcode)
Definition spc700.cc:55
void MOVY(uint16_t adr)
void ORM(uint16_t dest, uint8_t operand)
uint16_t ind()
Definition addressing.cc:8
uint8_t ReadOpcode()
Definition spc700.h:152
Flags ByteToFlags(uint8_t byte)
Definition spc700.h:122
void RunOpcode()
Definition spc700.cc:27
SNES Emulation and debugging tools.
Definition apu.cc:13
Main namespace for the application.
Definition controller.cc:18