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