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