yaze 0.3.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
10#include "core/features.h"
11#include "util/log.h"
12
13namespace yaze {
14namespace emu {
15
16void Spc700::Reset(bool hard) {
17 if (hard) {
18 // DON'T set PC = 0 here! The reset sequence in Step() will load PC from the
19 // reset vector. Setting PC = 0 here would overwrite the correct value
20 // loaded from $FFFE-$FFFF.
21 A = 0;
22 X = 0;
23 Y = 0;
24 SP = 0x00;
25 PSW = ByteToFlags(0x00);
26 }
27 step = 0;
28 stopped_ = false;
29 reset_wanted_ = true;
30}
31
33 // Handle reset sequence (based on 6502, brk without writes)
34 if (reset_wanted_) {
35 reset_wanted_ = false;
36 read(PC);
37 read(PC);
38 read(0x100 | SP--);
39 read(0x100 | SP--);
40 read(0x100 | SP--);
41 callbacks_.idle(false);
42 PSW.I = false;
43
44 // Load PC from reset vector ($FFFE-$FFFF)
45 uint8_t lo = read(0xfffe);
46 uint8_t hi = read(0xffff);
47 PC = lo | (hi << 8);
48
49 return 8;
50 }
51
52 // Handle stopped state (SLEEP/STOP instructions)
53 if (stopped_) {
54 callbacks_.idle(true);
55 return 2;
56 }
57
58 // Reset extra cycle counter for new instruction
59 extra_cycles_ = 0;
60
61 // Fetch and execute one complete instruction
62 uint8_t opcode = ReadOpcode();
63
64 // Get base cycle count from the new accurate lookup table
65 int cycles = spc700_cycles[opcode];
66
67 // Execute the instruction completely (atomic execution)
68 // This will set extra_cycles_ if a branch is taken
70
71 // Return the base cycles plus any extra cycles from branching
72 return cycles + extra_cycles_;
73}
74
76 // Multi-stage instruction execution
77 // step 0: Fetch opcode and initialize instruction (only if previous instruction complete)
78 // step 1: Execute instruction logic (may require multiple calls/cycles for complex ops)
79 // bstep: Tracks sub-steps within a single instruction execution (e.g., read low byte, read high byte)
80
81 static int entry_log = 0;
82 if ((PC >= 0xFFF0 && PC <= 0xFFFF) && entry_log++ < 5) {
83 LOG_DEBUG("SPC", "RunOpcode ENTRY: PC=$%04X step=%d bstep=%d", PC, step,
84 bstep);
85 }
86
87 if (reset_wanted_) {
88 // based on 6502, brk without writes
89 reset_wanted_ = false;
90 read(PC);
91 read(PC);
92 read(0x100 | SP--);
93 read(0x100 | SP--);
94 read(0x100 | SP--);
95 callbacks_.idle(false);
96 PSW.I = false;
97 PC = read_word(0xfffe);
98 last_opcode_cycles_ = 8; // Reset sequence takes 8 cycles
99 return;
100 }
101 if (stopped_) {
102 // Allow timers/DSP to continue advancing while SPC is stopped/sleeping.
103 callbacks_.idle(true);
104 last_opcode_cycles_ = 2; // Stopped state consumes minimal cycles
105 return;
106 }
107 if (step == 0) {
108 // Debug: Comprehensive IPL ROM tracing for transfer protocol debugging
109 // (Only enabled for first few iterations to avoid log spam)
110 static int spc_exec_count = 0;
111 bool in_critical_range = (PC >= 0xFFCF && PC <= 0xFFFF);
112 bool is_transfer_loop = (PC >= 0xFFD6 && PC <= 0xFFED);
113
114 // Reduced logging limits - only log first few iterations
115 if (in_critical_range && spc_exec_count++ < 5) {
116 LOG_DEBUG("SPC", "Execute: PC=$%04X step=0 bstep=%d Y=%02X A=%02X", PC,
117 bstep, Y, A);
118 }
119 if (is_transfer_loop && spc_exec_count < 10) {
120 // Read ports and RAM[$00] to track transfer state
121 uint8_t f4_val = callbacks_.read(0xF4);
122 uint8_t f5_val = callbacks_.read(0xF5);
123 uint8_t ram0_val = callbacks_.read(0x00);
124 LOG_DEBUG("SPC",
125 "TRANSFER LOOP: PC=$%04X Y=%02X A=%02X F4=%02X F5=%02X "
126 "RAM0=%02X bstep=%d",
127 PC, Y, A, f4_val, f5_val, ram0_val, bstep);
128 }
129
130 // Only read new opcode if previous instruction is complete
131 if (bstep == 0) {
132 opcode = ReadOpcode();
133 // Set base cycle count from lookup table
135 } else {
136 if (spc_exec_count < 5) {
137 LOG_DEBUG("SPC",
138 "Continuing multi-step: PC=$%04X bstep=%d opcode=$%02X", PC,
139 bstep, opcode);
140 }
141 }
142 step = 1;
143 return;
144 }
145 // TODO: Add SPC700 DisassemblyViewer similar to CPU
146 // For now, skip logging to avoid performance overhead
147 // SPC700 runs at ~1.024 MHz, logging every instruction would be expensive
148 // without the sparse address-map optimization
149
150 static int exec_log = 0;
151 if ((PC >= 0xFFF0 && PC <= 0xFFFF) && exec_log++ < 5) {
152 LOG_DEBUG(
153 "SPC",
154 "About to ExecuteInstructions: PC=$%04X step=%d bstep=%d opcode=$%02X",
155 PC, step, bstep, opcode);
156 }
157
159 // Only reset step if instruction is complete (bstep back to 0)
160 static int reset_log = 0;
161 if (step == 1) {
162 if (bstep == 0) {
163 if ((PC >= 0xFFF0 && PC <= 0xFFFF) && reset_log++ < 5) {
164 LOG_DEBUG("SPC", "Resetting step: PC=$%04X opcode=$%02X bstep=%d", PC,
165 opcode, bstep);
166 }
167 step = 0;
168 } else {
169 if ((PC >= 0xFFF0 && PC <= 0xFFFF) && reset_log++ < 5) {
170 LOG_DEBUG("SPC", "NOT resetting step: PC=$%04X opcode=$%02X bstep=%d",
171 PC, opcode, bstep);
172 }
173 }
174 }
175}
176
177void Spc700::ExecuteInstructions(uint8_t opcode) {
178 switch (opcode) {
179 case 0x00: { // nop imp
180 read(PC);
181 // no operation
182 break;
183 }
184 case 0x01:
185 case 0x11:
186 case 0x21:
187 case 0x31:
188 case 0x41:
189 case 0x51:
190 case 0x61:
191 case 0x71:
192 case 0x81:
193 case 0x91:
194 case 0xa1:
195 case 0xb1:
196 case 0xc1:
197 case 0xd1:
198 case 0xe1:
199 case 0xf1: { // tcall imp
200 read(PC);
201 callbacks_.idle(false);
202 push_word(PC);
203 callbacks_.idle(false);
204 uint16_t adr = 0xffde - (2 * (opcode >> 4));
205 PC = read_word(adr);
206 break;
207 }
208 case 0x02:
209 case 0x22:
210 case 0x42:
211 case 0x62:
212 case 0x82:
213 case 0xa2:
214 case 0xc2:
215 case 0xe2: { // set1 dp
216 uint16_t adr = dp();
217 write(adr, read(adr) | (1 << (opcode >> 5)));
218 break;
219 }
220 case 0x12:
221 case 0x32:
222 case 0x52:
223 case 0x72:
224 case 0x92:
225 case 0xb2:
226 case 0xd2:
227 case 0xf2: { // clr1 dp
228 uint16_t adr = dp();
229 write(adr, read(adr) & ~(1 << (opcode >> 5)));
230 break;
231 }
232 case 0x03:
233 case 0x23:
234 case 0x43:
235 case 0x63:
236 case 0x83:
237 case 0xa3:
238 case 0xc3:
239 case 0xe3: { // bbs dp, rel
240 uint8_t val = read(dp());
241 callbacks_.idle(false);
242 DoBranch(ReadOpcode(), val & (1 << (opcode >> 5)));
243 break;
244 }
245 case 0x13:
246 case 0x33:
247 case 0x53:
248 case 0x73:
249 case 0x93:
250 case 0xb3:
251 case 0xd3:
252 case 0xf3: { // bbc dp, rel
253 uint8_t val = read(dp());
254 callbacks_.idle(false);
255 DoBranch(ReadOpcode(), (val & (1 << (opcode >> 5))) == 0);
256 break;
257 }
258
259 case 0x04: { // or dp
260 OR(dp());
261 break;
262 }
263 case 0x05: { // or abs
264 OR(abs());
265 break;
266 }
267 case 0x06: { // or ind
268 OR(ind());
269 break;
270 }
271 case 0x07: { // or idx
272 OR(idx());
273 break;
274 }
275 case 0x08: { // or imm
276 OR(imm());
277 break;
278 }
279 case 0x09: { // orm dp, dp
280 uint8_t src = 0;
281 uint16_t dst = dp_dp(&src);
282 ORM(dst, src);
283 break;
284 }
285 case 0x0a: { // or1 abs.bit
286 uint16_t adr = 0;
287 uint8_t bit = abs_bit(&adr);
288 PSW.C = PSW.C | ((read(adr) >> bit) & 1);
289 callbacks_.idle(false);
290 break;
291 }
292 case 0x0b: { // asl dp
293 ASL(dp());
294 break;
295 }
296 case 0x0c: { // asl abs
297 ASL(abs());
298 break;
299 }
300 case 0x0d: { // pushp imp
301 read(PC);
303 callbacks_.idle(false);
304 break;
305 }
306 case 0x0e: { // tset1 abs
307 uint16_t adr = abs();
308 uint8_t val = read(adr);
309 read(adr);
310 uint8_t result = A + (val ^ 0xff) + 1;
311 PSW.Z = (result == 0);
312 PSW.N = (result & 0x80);
313 write(adr, val | A);
314 break;
315 }
316 case 0x0f: { // brk imp
317 read(PC);
318 push_word(PC);
320 callbacks_.idle(false);
321 PSW.I = false;
322 PSW.B = true;
323 PC = read_word(0xffde);
324 break;
325 }
326 case 0x10: { // bpl rel
328 break;
329 }
330 case 0x14: { // or dpx
331 OR(dpx());
332 break;
333 }
334 case 0x15: { // or abx
335 OR(abs_x());
336 break;
337 }
338 case 0x16: { // or aby
339 OR(abs_y());
340 break;
341 }
342 case 0x17: { // or idy
343 OR(idy());
344 break;
345 }
346 case 0x18: { // orm dp, imm
347 uint8_t src = 0;
348 uint16_t dst = dp_imm(&src);
349 ORM(dst, src);
350 break;
351 }
352 case 0x19: { // orm ind, ind
353 uint8_t src = 0;
354 uint16_t dst = ind_ind(&src);
355 ORM(dst, src);
356 break;
357 }
358 case 0x1a: { // decw dp
359 uint16_t low = 0;
360 uint16_t high = dp_word(&low);
361 uint16_t value = read(low) - 1;
362 write(low, value & 0xff);
363 value += read(high) << 8;
364 write(high, value >> 8);
365 PSW.Z = value == 0;
366 PSW.N = value & 0x8000;
367 break;
368 }
369 case 0x1b: { // asl dpx
370 ASL(dpx());
371 break;
372 }
373 case 0x1c: { // asla imp
374 read(PC);
375 PSW.C = A & 0x80;
376 A <<= 1;
377 PSW.Z = (A == 0);
378 PSW.N = (A & 0x80);
379 break;
380 }
381 case 0x1d: { // decx imp
382 read(PC);
383 X--;
384 PSW.Z = (X == 0);
385 PSW.N = (X & 0x80);
386 break;
387 }
388 case 0x1e: { // cmpx abs
389 CMPX(abs());
390 break;
391 }
392 case 0x1f: { // jmp iax
393 uint16_t pointer = ReadOpcodeWord();
394 callbacks_.idle(false);
395 PC = read_word((pointer + X) & 0xffff);
396 break;
397 }
398 case 0x20: { // clrp imp
399 read(PC);
400 PSW.P = false;
401 break;
402 }
403 case 0x24: { // and dp
404 AND(dp());
405 break;
406 }
407 case 0x25: { // and abs
408 AND(abs());
409 break;
410 }
411 case 0x26: { // and ind
412 AND(ind());
413 break;
414 }
415 case 0x27: { // and idx
416 AND(idx());
417 break;
418 }
419 case 0x28: { // and imm
420 AND(imm());
421 break;
422 }
423 case 0x29: { // andm dp, dp
424 uint8_t src = 0;
425 uint16_t dst = dp_dp(&src);
426 ANDM(dst, src);
427 break;
428 }
429 case 0x2a: { // or1n abs.bit
430 uint16_t adr = 0;
431 uint8_t bit = abs_bit(&adr);
432 PSW.C = PSW.C | (~(read(adr) >> bit) & 1);
433 callbacks_.idle(false);
434 break;
435 }
436 case 0x2b: { // rol dp
437 ROL(dp());
438 break;
439 }
440 case 0x2c: { // rol abs
441 ROL(abs());
442 break;
443 }
444 case 0x2d: { // pusha imp
445 read(PC);
446 push_byte(A);
447 callbacks_.idle(false);
448 break;
449 }
450 case 0x2e: { // cbne dp, rel
451 uint8_t val = read(dp()) ^ 0xff;
452 callbacks_.idle(false);
453 uint8_t result = A + val + 1;
454 DoBranch(ReadOpcode(), result != 0);
455 break;
456 }
457 case 0x2f: { // bra rel
458 DoBranch(ReadOpcode(), true);
459 break;
460 }
461 case 0x30: { // bmi rel
463 break;
464 }
465 case 0x34: { // and dpx
466 AND(dpx());
467 break;
468 }
469 case 0x35: { // and abx
470 AND(abs_x());
471 break;
472 }
473 case 0x36: { // and aby
474 AND(abs_y());
475 break;
476 }
477 case 0x37: { // and idy
478 AND(idy());
479 break;
480 }
481 case 0x38: { // andm dp, imm
482 uint8_t src = 0;
483 uint16_t dst = dp_imm(&src);
484 ANDM(dst, src);
485 break;
486 }
487 case 0x39: { // andm ind, ind
488 uint8_t src = 0;
489 uint16_t dst = ind_ind(&src);
490 ANDM(dst, src);
491 break;
492 }
493 case 0x3a: { // incw dp
494 uint16_t low = 0;
495 uint16_t high = dp_word(&low);
496 uint16_t value = read(low) + 1;
497 write(low, value & 0xff);
498 value += read(high) << 8;
499 write(high, value >> 8);
500 PSW.Z = value == 0;
501 PSW.N = value & 0x8000;
502 break;
503 }
504 case 0x3b: { // rol dpx
505 ROL(dpx());
506 break;
507 }
508 case 0x3c: { // rola imp
509 read(PC);
510 bool newC = A & 0x80;
511 A = (A << 1) | PSW.C;
512 PSW.C = newC;
513 PSW.Z = (A == 0);
514 PSW.N = (A & 0x80);
515 break;
516 }
517 case 0x3d: { // incx imp
518 read(PC);
519 X++;
520 PSW.Z = (X == 0);
521 PSW.N = (X & 0x80);
522 break;
523 }
524 case 0x3e: { // cmpx dp
525 CMPX(dp());
526 break;
527 }
528 case 0x3f: { // call abs
529 uint16_t dst = ReadOpcodeWord();
530 callbacks_.idle(false);
531 push_word(PC);
532 callbacks_.idle(false);
533 callbacks_.idle(false);
534 PC = dst;
535 break;
536 }
537 case 0x40: { // setp imp
538 read(PC);
539 PSW.P = true;
540 break;
541 }
542 case 0x44: { // eor dp
543 EOR(dp());
544 break;
545 }
546 case 0x45: { // eor abs
547 EOR(abs());
548 break;
549 }
550 case 0x46: { // eor ind
551 EOR(ind());
552 break;
553 }
554 case 0x47: { // eor idx
555 EOR(idx());
556 break;
557 }
558 case 0x48: { // eor imm
559 EOR(imm());
560 break;
561 }
562 case 0x49: { // eorm dp, dp
563 uint8_t src = 0;
564 uint16_t dst = dp_dp(&src);
565 EORM(dst, src);
566 break;
567 }
568 case 0x4a: { // and1 abs.bit
569 uint16_t adr = 0;
570 uint8_t bit = abs_bit(&adr);
571 PSW.C = PSW.C & ((read(adr) >> bit) & 1);
572 break;
573 }
574 case 0x4b: { // lsr dp
575 LSR(dp());
576 break;
577 }
578 case 0x4c: { // lsr abs
579 LSR(abs());
580 break;
581 }
582 case 0x4d: { // pushx imp
583 read(PC);
584 push_byte(X);
585 callbacks_.idle(false);
586 break;
587 }
588 case 0x4e: { // tclr1 abs
589 uint16_t adr = abs();
590 uint8_t val = read(adr);
591 read(adr);
592 uint8_t result = A + (val ^ 0xff) + 1;
593 PSW.Z = (result == 0);
594 PSW.N = (result & 0x80);
595 write(adr, val & ~A);
596 break;
597 }
598 case 0x4f: { // pcall dp
599 uint8_t dst = ReadOpcode();
600 callbacks_.idle(false);
601 push_word(PC);
602 callbacks_.idle(false);
603 PC = 0xff00 | dst;
604 break;
605 }
606 case 0x50: { // bvc rel
608 break;
609 }
610 case 0x54: { // eor dpx
611 EOR(dpx());
612 break;
613 }
614 case 0x55: { // eor abx
615 EOR(abs_x());
616 break;
617 }
618 case 0x56: { // eor aby
619 EOR(abs_y());
620 break;
621 }
622 case 0x57: { // eor idy
623 EOR(idy());
624 break;
625 }
626 case 0x58: { // eorm dp, imm
627 uint8_t src = 0;
628 uint16_t dst = dp_imm(&src);
629 EORM(dst, src);
630 break;
631 }
632 case 0x59: { // eorm ind, ind
633 uint8_t src = 0;
634 uint16_t dst = ind_ind(&src);
635 EORM(dst, src);
636 break;
637 }
638 case 0x5a: { // cmpw dp
639 uint16_t low = 0;
640 // uint16_t high = dp_word(&low);
641 uint16_t value = read_word(low) ^ 0xffff;
642 uint16_t ya = A | (Y << 8);
643 int result = ya + value + 1;
644 PSW.C = result > 0xffff;
645 PSW.Z = (result & 0xffff) == 0;
646 PSW.N = result & 0x8000;
647 break;
648 }
649 case 0x5b: { // lsr dpx
650 LSR(dpx());
651 break;
652 }
653 case 0x5c: { // lsra imp
654 read(PC);
655 PSW.C = A & 1;
656 A >>= 1;
657 PSW.Z = (A == 0);
658 PSW.N = (A & 0x80);
659 break;
660 }
661 case 0x5d: { // movxa imp
662 read(PC);
663 X = A;
664 PSW.Z = (X == 0);
665 PSW.N = (X & 0x80);
666 break;
667 }
668 case 0x5e: { // cmpy abs
669 CMPY(abs());
670 break;
671 }
672 case 0x5f: { // jmp abs
673 PC = ReadOpcodeWord();
674 break;
675 }
676 case 0x60: { // clrc imp
677 read(PC);
678 PSW.C = false;
679 break;
680 }
681 case 0x64: { // cmp dp
682 CMP(dp());
683 break;
684 }
685 case 0x65: { // cmp abs
686 CMP(abs());
687 break;
688 }
689 case 0x66: { // cmp ind
690 CMP(ind());
691 break;
692 }
693 case 0x67: { // cmp idx
694 CMP(idx());
695 break;
696 }
697 case 0x68: { // cmp imm
698 CMP(imm());
699 break;
700 }
701 case 0x69: { // cmpm dp, dp
702 uint8_t src = 0;
703 uint16_t dst = dp_dp(&src);
704 CMPM(dst, src);
705 break;
706 }
707 case 0x6a: { // and1n abs.bit
708 uint16_t adr = 0;
709 uint8_t bit = abs_bit(&adr);
710 PSW.C = PSW.C & (~(read(adr) >> bit) & 1);
711 break;
712 }
713 case 0x6b: { // ror dp
714 ROR(dp());
715 break;
716 }
717 case 0x6c: { // ror abs
718 ROR(abs());
719 break;
720 }
721 case 0x6d: { // pushy imp
722 read(PC);
723 push_byte(Y);
724 callbacks_.idle(false);
725 break;
726 }
727 case 0x6e: { // dbnz dp, rel
728 uint16_t adr = dp();
729 uint8_t result = read(adr) - 1;
730 write(adr, result);
731 DoBranch(ReadOpcode(), result != 0);
732 break;
733 }
734 case 0x6f: { // ret imp
735 read(PC);
736 callbacks_.idle(false);
737 PC = pull_word();
738 break;
739 }
740 case 0x70: { // bvs rel
742 break;
743 }
744 case 0x74: { // cmp dpx
745 CMP(dpx());
746 break;
747 }
748 case 0x75: { // cmp abx
749 CMP(abs_x());
750 break;
751 }
752 case 0x76: { // cmp aby
753 CMP(abs_y());
754 break;
755 }
756 case 0x77: { // cmp idy
757 CMP(idy());
758 break;
759 }
760 case 0x78: { // cmp d, #i
761 uint8_t imm = ReadOpcode();
762 uint16_t adr = (PSW.P << 8) | ReadOpcode();
763 uint8_t val = read(adr);
764 callbacks_.idle(false); // Add missing cycle
765 callbacks_.idle(false); // Add missing cycle
766 int result = val - imm;
767 PSW.C = (val >= imm);
768 PSW.Z = (result == 0);
769 PSW.N = (result & 0x80);
770 break;
771 }
772 case 0x79: { // cmpm ind, ind
773 uint8_t src = 0;
774 uint16_t dst = ind_ind(&src);
775 CMPM(dst, src);
776 break;
777 }
778 case 0x7a: { // addw dp
779 uint16_t low = 0;
780 uint16_t high = dp_word(&low);
781 uint8_t vall = read(low);
782 callbacks_.idle(false);
783 uint16_t value = vall | (read(high) << 8);
784 uint16_t ya = A | (Y << 8);
785 int result = ya + value;
786 PSW.V = (ya & 0x8000) == (value & 0x8000) &&
787 (value & 0x8000) != (result & 0x8000);
788 PSW.H = ((ya & 0xfff) + (value & 0xfff)) > 0xfff;
789 PSW.C = result > 0xffff;
790 PSW.Z = (result & 0xffff) == 0;
791 PSW.N = result & 0x8000;
792 A = result & 0xff;
793 Y = result >> 8;
794 break;
795 }
796 case 0x7b: { // ror dpx
797 ROR(dpx());
798 break;
799 }
800 case 0x7c: { // rora imp
801 read(PC);
802 bool newC = A & 1;
803 A = (A >> 1) | (PSW.C << 7);
804 PSW.C = newC;
805 PSW.Z = (A == 0);
806 PSW.N = (A & 0x80);
807 break;
808 }
809 case 0x7d: { // movax imp
810 read(PC);
811 A = X;
812 PSW.Z = (A == 0);
813 PSW.N = (A & 0x80);
814 break;
815 }
816 case 0x7e: { // cmpy dp
817 CMPY(dp());
818 break;
819 }
820 case 0x7f: { // reti imp
821 read(PC);
822 callbacks_.idle(false);
824 PC = pull_word();
825 break;
826 }
827 case 0x80: { // setc imp
828 read(PC);
829 PSW.C = true;
830 break;
831 }
832 case 0x84: { // adc dp
833 ADC(dp());
834 break;
835 }
836 case 0x85: { // adc abs
837 ADC(abs());
838 break;
839 }
840 case 0x86: { // adc ind
841 ADC(ind());
842 break;
843 }
844 case 0x87: { // adc idx
845 ADC(idx());
846 break;
847 }
848 case 0x88: { // adc imm
849 ADC(imm());
850 break;
851 }
852 case 0x89: { // adcm dp, dp
853 uint8_t src = 0;
854 uint16_t dst = dp_dp(&src);
855 ADCM(dst, src);
856 break;
857 }
858 case 0x8a: { // eor1 abs.bit
859 uint16_t adr = 0;
860 uint8_t bit = abs_bit(&adr);
861 PSW.C = PSW.C ^ ((read(adr) >> bit) & 1);
862 callbacks_.idle(false);
863 break;
864 }
865 case 0x8b: { // dec dp
866 DEC(dp());
867 break;
868 }
869 case 0x8c: { // dec abs
870 DEC(abs());
871 break;
872 }
873 case 0x8d: { // movy imm
874 MOVY(imm());
875 break;
876 }
877 case 0x8e: { // popp imp
878 read(PC);
879 callbacks_.idle(false);
881 break;
882 }
883 case 0x8f: { // movm dp, imm
884 uint8_t val = 0;
885 uint16_t dst = dp_imm(&val);
886 read(dst);
887 write(dst, val);
888 break;
889 }
890 case 0x90: { // bcc rel
892 break;
893 }
894 case 0x94: { // adc dpx
895 ADC(dpx());
896 break;
897 }
898 case 0x95: { // adc abx
899 ADC(abs_x());
900 break;
901 }
902 case 0x96: { // adc aby
903 ADC(abs_y());
904 break;
905 }
906 case 0x97: { // adc idy
907 ADC(idy());
908 break;
909 }
910 case 0x98: { // adcm dp, imm
911 uint8_t src = 0;
912 uint16_t dst = dp_imm(&src);
913 ADCM(dst, src);
914 break;
915 }
916 case 0x99: { // adcm ind, ind
917 uint8_t src = 0;
918 uint16_t dst = ind_ind(&src);
919 ADCM(dst, src);
920 break;
921 }
922 case 0x9a: { // subw dp
923 uint16_t low = 0;
924 uint16_t high = dp_word(&low);
925 uint8_t vall = read(low);
926 callbacks_.idle(false);
927 uint16_t value = (vall | (read(high) << 8)) ^ 0xffff;
928 uint16_t ya = A | (Y << 8);
929 int result = ya + value + 1;
930 PSW.V = (ya & 0x8000) == (value & 0x8000) &&
931 (value & 0x8000) != (result & 0x8000);
932 PSW.H = ((ya & 0xfff) + (value & 0xfff) + 1) > 0xfff;
933 PSW.C = result > 0xffff;
934 PSW.Z = (result & 0xffff) == 0;
935 PSW.N = result & 0x8000;
936 A = result & 0xff;
937 Y = result >> 8;
938 break;
939 }
940 case 0x9b: { // dec dpx
941 DEC(dpx());
942 break;
943 }
944 case 0x9c: { // deca imp
945 read(PC);
946 A--;
947 PSW.Z = (A == 0);
948 PSW.N = (A & 0x80);
949 break;
950 }
951 case 0x9d: { // movxp imp
952 read(PC);
953 X = SP;
954 PSW.Z = (X == 0);
955 PSW.N = (X & 0x80);
956 break;
957 }
958 case 0x9e: { // div imp
959 read(PC);
960 for (int i = 0; i < 10; i++)
961 callbacks_.idle(false);
962 PSW.H = (X & 0xf) <= (Y & 0xf);
963 int yva = (Y << 8) | A;
964 int x = X << 9;
965 for (int i = 0; i < 9; i++) {
966 yva <<= 1;
967 yva |= (yva & 0x20000) ? 1 : 0;
968 yva &= 0x1ffff;
969 if (yva >= x)
970 yva ^= 1;
971 if (yva & 1)
972 yva -= x;
973 yva &= 0x1ffff;
974 }
975 Y = yva >> 9;
976 PSW.V = yva & 0x100;
977 A = yva & 0xff;
978 PSW.Z = (A == 0);
979 PSW.N = (A & 0x80);
980 break;
981 }
982 case 0x9f: { // xcn imp
983 read(PC);
984 callbacks_.idle(false);
985 callbacks_.idle(false);
986 callbacks_.idle(false);
987 A = (A >> 4) | (A << 4);
988 PSW.Z = (A == 0);
989 PSW.N = (A & 0x80);
990 break;
991 }
992 case 0xa0: { // ei imp
993 read(PC);
994 callbacks_.idle(false);
995 PSW.I = true;
996 break;
997 }
998 case 0xa4: { // sbc dp
999 SBC(dp());
1000 break;
1001 }
1002 case 0xa5: { // sbc abs
1003 SBC(abs());
1004 break;
1005 }
1006 case 0xa6: { // sbc ind
1007 SBC(ind());
1008 break;
1009 }
1010 case 0xa7: { // sbc idx
1011 SBC(idx());
1012 break;
1013 }
1014 case 0xa8: { // sbc imm
1015 SBC(imm());
1016 break;
1017 }
1018 case 0xa9: { // sbcm dp, dp
1019 uint8_t src = 0;
1020 uint16_t dst = dp_dp(&src);
1021 SBCM(dst, src);
1022 break;
1023 }
1024 case 0xaa: { // mov1 abs.bit
1025 uint16_t adr = 0;
1026 uint8_t bit = abs_bit(&adr);
1027 PSW.C = (read(adr) >> bit) & 1;
1028 break;
1029 }
1030 case 0xab: { // inc dp
1031 INC(dp());
1032 break;
1033 }
1034 case 0xac: { // inc abs
1035 INC(abs());
1036 break;
1037 }
1038 case 0xad: { // cmpy imm
1039 CMPY(imm());
1040 break;
1041 }
1042 case 0xae: { // popa imp
1043 read(PC);
1044 callbacks_.idle(false);
1045 A = pull_byte();
1046 break;
1047 }
1048 case 0xaf: { // movs ind+
1049 uint16_t adr = ind_p();
1050 callbacks_.idle(false);
1051 write(adr, A);
1052 break;
1053 }
1054 case 0xb0: { // bcs rel
1056 break;
1057 }
1058 case 0xb4: { // sbc dpx
1059 SBC(dpx());
1060 break;
1061 }
1062 case 0xb5: { // sbc abx
1063 SBC(abs_x());
1064 break;
1065 }
1066 case 0xb6: { // sbc aby
1067 SBC(abs_y());
1068 break;
1069 }
1070 case 0xb7: { // sbc idy
1071 SBC(idy());
1072 break;
1073 }
1074 case 0xb8: { // sbcm dp, imm
1075 uint8_t src = 0;
1076 uint16_t dst = dp_imm(&src);
1077 SBCM(dst, src);
1078 break;
1079 }
1080 case 0xb9: { // sbcm ind, ind
1081 uint8_t src = 0;
1082 uint16_t dst = ind_ind(&src);
1083 SBCM(dst, src);
1084 break;
1085 }
1086 case 0xba: { // movw dp
1087 uint16_t low = 0;
1088 uint16_t high = dp_word(&low);
1089 uint8_t vall = read(low);
1090 callbacks_.idle(false);
1091 uint16_t val = vall | (read(high) << 8);
1092 A = val & 0xff;
1093 Y = val >> 8;
1094 PSW.Z = val == 0;
1095 PSW.N = val & 0x8000;
1096 break;
1097 }
1098 case 0xbb: { // inc dpx
1099 INC(dpx());
1100 break;
1101 }
1102 case 0xbc: { // inca imp
1103 read(PC);
1104 A++;
1105 PSW.Z = (A == 0);
1106 PSW.N = (A & 0x80);
1107 ;
1108 break;
1109 }
1110 case 0xbd: { // movpx imp
1111 read(PC);
1112 SP = X;
1113 break;
1114 }
1115 case 0xbe: { // das imp
1116 read(PC);
1117 callbacks_.idle(false);
1118 if (A > 0x99 || !PSW.C) {
1119 A -= 0x60;
1120 PSW.C = false;
1121 }
1122 if ((A & 0xf) > 9 || !PSW.H) {
1123 A -= 6;
1124 }
1125 PSW.Z = (A == 0);
1126 PSW.N = (A & 0x80);
1127 break;
1128 }
1129 case 0xbf: { // mov ind+
1130 uint16_t adr = ind_p();
1131 A = read(adr);
1132 callbacks_.idle(false);
1133 PSW.Z = (A == 0);
1134 PSW.N = (A & 0x80);
1135 break;
1136 }
1137 case 0xc0: { // di imp
1138 read(PC);
1139 callbacks_.idle(false);
1140 PSW.I = false;
1141 break;
1142 }
1143 case 0xc4: { // movs dp
1144 uint16_t adr = dp();
1145 MOVS(adr);
1146 break;
1147 }
1148 case 0xc5: { // movs abs
1149 MOVS(abs());
1150 break;
1151 }
1152 case 0xc6: { // movs ind
1153 MOVS(ind());
1154 break;
1155 }
1156 case 0xc7: { // movs idx
1157 MOVS(idx());
1158 break;
1159 }
1160 case 0xc8: { // cmpx imm
1161 CMPX(imm());
1162 break;
1163 }
1164 case 0xc9: { // movsx abs
1165 MOVSX(abs());
1166 break;
1167 }
1168 case 0xca: { // mov1s abs.bit
1169 uint16_t adr = 0;
1170 uint8_t bit = abs_bit(&adr);
1171 uint8_t result = (read(adr) & (~(1 << bit))) | (PSW.C << bit);
1172 callbacks_.idle(false);
1173 write(adr, result);
1174 break;
1175 }
1176 case 0xcb: { // mov d, Y
1177 uint16_t adr = (PSW.P << 8) | ReadOpcode();
1178 read(adr);
1179 callbacks_.idle(false); // Add one extra cycle delay
1180 write(adr, Y);
1181 break;
1182 }
1183 case 0xcc: { // movsy abs
1184 MOVSY(abs());
1185 break;
1186 }
1187 case 0xcd: { // movx imm
1188 MOVX(imm());
1189 break;
1190 }
1191 case 0xce: { // popx imp
1192 read(PC);
1193 callbacks_.idle(false);
1194 X = pull_byte();
1195 break;
1196 }
1197 case 0xcf: { // mul imp
1198 read(PC);
1199 for (int i = 0; i < 7; i++)
1200 callbacks_.idle(false);
1201 uint16_t result = A * Y;
1202 A = result & 0xff;
1203 Y = result >> 8;
1204 PSW.Z = (Y == 0);
1205 PSW.N = (Y & 0x80);
1206 break;
1207 }
1208 case 0xd0: { // bne rel
1209 DoBranch(ReadOpcode(), !PSW.Z);
1210 break;
1211 }
1212 case 0xd4: { // movs dpx
1213 MOVS(dpx());
1214 break;
1215 }
1216 case 0xd5: { // movs abx
1217 MOVS(abs_x());
1218 break;
1219 }
1220 case 0xd6: { // movs aby
1221 MOVS(abs_y());
1222 break;
1223 }
1224 case 0xd7: { // movs idy
1225 // CRITICAL: Only call idy() once in bstep=0, reuse saved address in
1226 // bstep=1
1227 if (bstep == 0) {
1228 adr = idy(); // Save address for bstep=1
1229 }
1230 MOVS(adr); // Use saved address
1231 break;
1232 }
1233 case 0xd8: { // movsx dp
1234 MOVSX(dp());
1235 break;
1236 }
1237 case 0xd9: { // movsx dpy
1238 MOVSX(dp_y());
1239 break;
1240 }
1241 case 0xda: { // movws dp
1242 uint16_t low = 0;
1243 uint16_t high = dp_word(&low);
1244 read(low);
1245 write(low, A);
1246 write(high, Y);
1247 break;
1248 }
1249 case 0xdb: { // movsy dpx
1250 MOVSY(dpx());
1251 break;
1252 }
1253 case 0xdc: { // decy imp
1254 read(PC);
1255 Y--;
1256 PSW.Z = (Y == 0);
1257 PSW.N = (Y & 0x80);
1258 break;
1259 }
1260 case 0xdd: { // movay imp
1261 read(PC);
1262 A = Y;
1263 PSW.Z = (A == 0);
1264 PSW.N = (A & 0x80);
1265 break;
1266 }
1267 case 0xde: { // cbne dpx, rel
1268 uint8_t val = read(dpx()) ^ 0xff;
1269 callbacks_.idle(false);
1270 uint8_t result = A + val + 1;
1271 DoBranch(ReadOpcode(), result != 0);
1272 break;
1273 }
1274 case 0xdf: { // daa imp
1275 read(PC);
1276 callbacks_.idle(false);
1277 if (A > 0x99 || PSW.C) {
1278 A += 0x60;
1279 PSW.C = true;
1280 }
1281 if ((A & 0xf) > 9 || PSW.H) {
1282 A += 6;
1283 }
1284 PSW.Z = (A == 0);
1285 PSW.N = (A & 0x80);
1286 break;
1287 }
1288 case 0xe0: { // clrv imp
1289 read(PC);
1290 PSW.V = false;
1291 PSW.H = false;
1292 break;
1293 }
1294 case 0xe4: { // mov A, dp
1295 uint16_t adr = (PSW.P << 8) | ReadOpcode();
1296 A = read(adr);
1297 PSW.Z = (A == 0);
1298 PSW.N = (A & 0x80);
1299 break;
1300 }
1301 case 0xe5: { // mov A, abs
1302 uint16_t adr = ReadOpcodeWord();
1303 A = read(adr);
1304 PSW.Z = (A == 0);
1305 PSW.N = (A & 0x80);
1306 break;
1307 }
1308 case 0xe6: { // mov A, (X)
1309 uint16_t adr = X;
1310 A = read(adr);
1311 PSW.Z = (A == 0);
1312 PSW.N = (A & 0x80);
1313 break;
1314 }
1315 case 0xe7: { // mov A, [dp+X]
1316 uint16_t dp_adr = (PSW.P << 8) | ReadOpcode();
1317 callbacks_.idle(false);
1318 uint16_t adr = read_word(dp_adr + X);
1319 A = read(adr);
1320 PSW.Z = (A == 0);
1321 PSW.N = (A & 0x80);
1322 break;
1323 }
1324 case 0xe8: { // mov A, #imm
1325 A = ReadOpcode();
1326 PSW.Z = (A == 0);
1327 PSW.N = (A & 0x80);
1328 break;
1329 }
1330 case 0xe9: { // movx abs
1331 uint16_t adr = ReadOpcodeWord();
1332 X = read(adr);
1333 PSW.Z = (X == 0);
1334 PSW.N = (X & 0x80);
1335 break;
1336 }
1337 case 0xeb: { // movy dp
1338 uint16_t adr = (PSW.P << 8) | ReadOpcode();
1339 callbacks_.idle(false); // Add missing cycle
1340 Y = read(adr);
1341 PSW.Z = (Y == 0);
1342 PSW.N = (Y & 0x80);
1343 break;
1344 }
1345 case 0xec: { // movy abs
1346 uint16_t adr = ReadOpcodeWord();
1347 Y = read(adr);
1348 PSW.Z = (Y == 0);
1349 PSW.N = (Y & 0x80);
1350 break;
1351 }
1352 case 0xed: { // notc imp
1353 read(PC);
1354 callbacks_.idle(false);
1355 PSW.C = !PSW.C;
1356 break;
1357 }
1358 case 0xee: { // popy imp
1359 read(PC);
1360 callbacks_.idle(false);
1361 Y = pull_byte();
1362 break;
1363 }
1364 case 0xef: { // sleep imp
1365 // Emulate low-power idle without halting the core permanently.
1366 // Advance timers/DSP via idle callbacks, but do not set stopped_.
1367 static int sleep_log = 0;
1368 if (sleep_log++ < 5) {
1369 LOG_DEBUG("SPC", "SLEEP executed at PC=$%04X - entering low power mode",
1370 PC - 1);
1371 }
1372 read(PC);
1373 for (int i = 0; i < 4; ++i)
1374 callbacks_.idle(true);
1375 break;
1376 }
1377 case 0xf0: { // beq rel
1379 break;
1380 }
1381 case 0xf4: { // mov dpx
1382 MOV(dpx());
1383 break;
1384 }
1385 case 0xf5: { // mov abx
1386 MOV(abs_x());
1387 break;
1388 }
1389 case 0xf6: { // mov aby
1390 MOV(abs_y());
1391 break;
1392 }
1393 case 0xf7: { // mov idy
1394 MOV(idy());
1395 break;
1396 }
1397 case 0xf8: { // movx dp
1398 MOVX(dp());
1399 break;
1400 }
1401 case 0xf9: { // movx dpy
1402 MOVX(dp_y());
1403 break;
1404 }
1405 case 0xfa: { // movm dp, dp
1406 uint8_t val = 0;
1407 uint16_t dst = dp_dp(&val);
1408 write(dst, val);
1409 break;
1410 }
1411 case 0xfb: { // movy dpx
1412 MOVY(dpx());
1413 break;
1414 }
1415 case 0xfc: { // incy imp
1416 uint8_t old_y = Y;
1417 read(PC);
1418 Y++;
1419 PSW.Z = (Y == 0);
1420 PSW.N = (Y & 0x80);
1421 // Log Y increment in transfer loop for first few iterations only
1422 static int incy_log = 0;
1423 if (PC >= 0xFFE4 && PC <= 0xFFE6 && incy_log++ < 10) {
1424 LOG_DEBUG("SPC",
1425 "INC Y executed at PC=$%04X: Y changed from $%02X to $%02X "
1426 "(Z=%d N=%d)",
1427 PC - 1, old_y, Y, PSW.Z, PSW.N);
1428 }
1429 break;
1430 }
1431 case 0xfd: { // movya imp
1432 read(PC);
1433 Y = A;
1434 PSW.Z = (Y == 0);
1435 PSW.N = (Y & 0x80);
1436 break;
1437 }
1438 case 0xfe: { // dbnzy rel
1439 read(PC);
1440 callbacks_.idle(false);
1441 Y--;
1442 DoBranch(ReadOpcode(), Y != 0);
1443 break;
1444 }
1445 case 0xff: { // stop imp
1446 read(PC);
1447 callbacks_.idle(false);
1448 stopped_ = true;
1449 break;
1450 }
1451
1452 default:
1453 throw std::runtime_error("Unknown SPC opcode: " + std::to_string(opcode));
1454 break;
1455 }
1456}
1457
1458void Spc700::LogInstruction(uint16_t initial_pc, uint8_t opcode) {
1459 const std::string& mnemonic = spc_opcode_map.at(opcode);
1460
1461 std::stringstream ss;
1462 ss << "$" << std::hex << std::setw(4) << std::setfill('0') << initial_pc
1463 << ": 0x" << std::setw(2) << std::setfill('0') << static_cast<int>(opcode)
1464 << " " << mnemonic << " A:" << std::setw(2) << std::setfill('0')
1465 << std::hex << static_cast<int>(A) << " X:" << std::setw(2)
1466 << std::setfill('0') << std::hex << static_cast<int>(X)
1467 << " Y:" << std::setw(2) << std::setfill('0') << std::hex
1468 << static_cast<int>(Y);
1469
1471 ss.str());
1472}
1473
1474void Spc700::SaveState(std::ostream& stream) {
1475 stream.write(reinterpret_cast<const char*>(&stopped_), sizeof(stopped_));
1476 stream.write(reinterpret_cast<const char*>(&reset_wanted_), sizeof(reset_wanted_));
1477
1478 stream.write(reinterpret_cast<const char*>(&opcode), sizeof(opcode));
1479 stream.write(reinterpret_cast<const char*>(&step), sizeof(step));
1480 stream.write(reinterpret_cast<const char*>(&bstep), sizeof(bstep));
1481 stream.write(reinterpret_cast<const char*>(&adr), sizeof(adr));
1482 stream.write(reinterpret_cast<const char*>(&adr1), sizeof(adr1));
1483 stream.write(reinterpret_cast<const char*>(&dat), sizeof(dat));
1484 stream.write(reinterpret_cast<const char*>(&dat16), sizeof(dat16));
1485 stream.write(reinterpret_cast<const char*>(&param), sizeof(param));
1486 stream.write(reinterpret_cast<const char*>(&extra_cycles_), sizeof(extra_cycles_));
1487 stream.write(reinterpret_cast<const char*>(&last_opcode_cycles_), sizeof(last_opcode_cycles_));
1488
1489 stream.write(reinterpret_cast<const char*>(&A), sizeof(A));
1490 stream.write(reinterpret_cast<const char*>(&X), sizeof(X));
1491 stream.write(reinterpret_cast<const char*>(&Y), sizeof(Y));
1492 stream.write(reinterpret_cast<const char*>(&YA), sizeof(YA));
1493 stream.write(reinterpret_cast<const char*>(&PC), sizeof(PC));
1494 stream.write(reinterpret_cast<const char*>(&SP), sizeof(SP));
1495 stream.write(reinterpret_cast<const char*>(&PSW), sizeof(PSW));
1496}
1497
1498void Spc700::LoadState(std::istream& stream) {
1499 stream.read(reinterpret_cast<char*>(&stopped_), sizeof(stopped_));
1500 stream.read(reinterpret_cast<char*>(&reset_wanted_), sizeof(reset_wanted_));
1501
1502 stream.read(reinterpret_cast<char*>(&opcode), sizeof(opcode));
1503 stream.read(reinterpret_cast<char*>(&step), sizeof(step));
1504 stream.read(reinterpret_cast<char*>(&bstep), sizeof(bstep));
1505 stream.read(reinterpret_cast<char*>(&adr), sizeof(adr));
1506 stream.read(reinterpret_cast<char*>(&adr1), sizeof(adr1));
1507 stream.read(reinterpret_cast<char*>(&dat), sizeof(dat));
1508 stream.read(reinterpret_cast<char*>(&dat16), sizeof(dat16));
1509 stream.read(reinterpret_cast<char*>(&param), sizeof(param));
1510 stream.read(reinterpret_cast<char*>(&extra_cycles_), sizeof(extra_cycles_));
1511 stream.read(reinterpret_cast<char*>(&last_opcode_cycles_), sizeof(last_opcode_cycles_));
1512
1513 stream.read(reinterpret_cast<char*>(&A), sizeof(A));
1514 stream.read(reinterpret_cast<char*>(&X), sizeof(X));
1515 stream.read(reinterpret_cast<char*>(&Y), sizeof(Y));
1516 stream.read(reinterpret_cast<char*>(&YA), sizeof(YA));
1517 stream.read(reinterpret_cast<char*>(&PC), sizeof(PC));
1518 stream.read(reinterpret_cast<char*>(&SP), sizeof(SP));
1519 stream.read(reinterpret_cast<char*>(&PSW), sizeof(PSW));
1520}
1521
1522} // namespace emu
1523} // namespace yaze
const std::unordered_map< uint8_t, std::string > spc_opcode_map
Definition opcodes.h:7
uint16_t adr1
Definition spc700.h:81
void CMPM(uint16_t dst, uint8_t value)
void MOVS(uint16_t adr)
uint16_t pull_word()
Definition spc700.h:208
uint8_t read(uint16_t address)
Definition spc700.h:157
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
uint16_t dat16
Definition spc700.h:83
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:16
void LoadState(std::istream &stream)
Definition spc700.cc:1498
void LSR(uint16_t adr)
void push_byte(uint8_t value)
Definition spc700.h:193
void CMPX(uint16_t adr)
uint8_t FlagsToByte(Flags flags)
Definition spc700.h:121
bool reset_wanted_
Definition spc700.h:75
void LogInstruction(uint16_t initial_pc, uint8_t opcode)
Definition spc700.cc:1458
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:171
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:189
uint8_t param
Definition spc700.h:84
void INC(uint16_t adr)
uint16_t abs_x()
Definition addressing.cc:31
void SaveState(std::ostream &stream)
Definition spc700.cc:1474
uint16_t dp_word(uint16_t *low)
Definition addressing.cc:67
void push_word(uint16_t value)
Definition spc700.h:198
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:159
void ASL(uint16_t operand)
uint16_t YA
Definition spc700.h:105
void OR(uint16_t adr)
void ADCM(uint16_t &dest, uint8_t operand)
int last_opcode_cycles_
Definition spc700.h:88
void DoBranch(uint8_t value, bool check)
Definition spc700.h:177
uint16_t PC
Definition spc700.h:106
void AND(uint16_t adr)
uint8_t pull_byte()
Definition spc700.h:203
ApuCallbacks callbacks_
Definition spc700.h:71
void MOVSY(uint16_t adr)
void ExecuteInstructions(uint8_t opcode)
Definition spc700.cc:177
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:166
Flags ByteToFlags(uint8_t byte)
Definition spc700.h:126
void RunOpcode()
Definition spc700.cc:75
static LogManager & instance()
Definition log.cc:31
void log(LogLevel level, absl::string_view category, absl::string_view message)
The primary logging function.
Definition log.cc:97
#define LOG_DEBUG(category, format,...)
Definition log.h:103
constexpr int spc700_cycles[256]
std::function< void(bool)> idle
Definition spc700.h:55
std::function< uint8_t(uint16_t)> read
Definition spc700.h:54