yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
cpu.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EMU_CPU_H_
2#define YAZE_APP_EMU_CPU_H_
3
4#include <algorithm>
5#include <cstdint>
6#include <vector>
7
9
10namespace yaze {
11namespace emu {
12
13// Forward declarations
14namespace debug {
15class DisassemblyViewer;
16}
17
19 public:
20 // Constructor
21 InstructionEntry(uint32_t addr, uint8_t op, const std::string& ops,
22 const std::string& instr)
23 : address(addr), opcode(op), operands(ops), instruction(instr) {}
24
25 // Getters for the class members
26 uint32_t GetAddress() const { return address; }
27 uint8_t GetOpcode() const { return opcode; }
28 const std::string& GetOperands() const { return operands; }
29 const std::string& GetInstruction() const { return instruction; }
30
31 uint32_t address; // Memory address of the instruction
32 uint8_t opcode; // Opcode of the instruction
33 std::string operands; // Operand(s) of the instruction, if any
34 std::string instruction; // Human-readable instruction text
35};
36
37class Cpu {
38 public:
39 explicit Cpu(Memory& mem) : memory(mem) {}
40 void Reset(bool hard = false);
41
42 void SaveState(std::ostream& stream);
43 void LoadState(std::istream& stream);
44
45 auto& callbacks() { return callbacks_; }
46 const auto& callbacks() const { return callbacks_; }
47
48 void RunOpcode();
49
50 void ExecuteInstruction(uint8_t opcode);
51 void LogInstructions(uint16_t PC, uint8_t opcode, uint16_t operand,
52 bool immediate, bool accumulator_mode);
53
54 void SetIrq(bool state) { irq_wanted_ = state; }
55 void Nmi() { nmi_wanted_ = true; }
56
57 std::vector<uint32_t> breakpoints_;
58 // REMOVED: instruction_log_ - replaced by efficient DisassemblyViewer
59
60 // Disassembly viewer (always enabled, uses sparse address map)
63
64 // Breakpoint callback (set by Emulator)
65 std::function<bool(uint32_t pc)> on_breakpoint_hit_;
66
67 // Instruction recording callback (for DisassemblyViewer)
68 std::function<void(
69 uint32_t address, uint8_t opcode, const std::vector<uint8_t>& operands,
70 const std::string& mnemonic, const std::string& operand_str)>
72
73 // Public register access for debugging and UI
74 uint16_t A = 0; // Accumulator
75 uint16_t X = 0; // X index register
76 uint16_t Y = 0; // Y index register
77 uint16_t D = 0; // Direct Page register
78 uint8_t DB = 0; // Data Bank register
79 uint8_t PB = 0; // Program Bank register
80 uint16_t PC = 0; // Program Counter
81 uint8_t status = 0b00110000; // Processor Status (P)
82
83 // Breakpoint management
84 void set_int_delay(bool delay) { int_delay_ = delay; }
85
87
88 // ======================================================
89 // Interrupt Vectors
90 // Emulation mode, e = 1 Native mode, e = 0
91 //
92 // 0xFFFE,FF - IRQ/BRK 0xFFEE,EF - IRQ
93 // 0xFFFC,FD - RESET
94 // 0xFFFA,FB - NMI 0xFFEA,EB - NMI
95 // 0xFFF8,F9 - ABORT 0xFFE8,E9 - ABORT
96 // 0xFFE6,E7 - BRK
97 // 0xFFF4,F5 - COP 0xFFE4,E5 - COP
98 void DoInterrupt();
99
100 // ======================================================
101 // Internal state
102
103 uint8_t E = 1; // Emulation mode flag
104
105 // Mnemonic Value Binary Description
106 // N #$80 10000000 Negative
107 // V #$40 01000000 Overflow
108 // M #$20 00100000 Accumulator size (0 = 16-bit, 1 = 8-bit)
109 // X #$10 00010000 Index size (0 = 16-bit, 1 = 8-bit)
110 // D #$08 00001000 Decimal
111 // I #$04 00000100 IRQ disable
112 // Z #$02 00000010 Zero
113 // C #$01 00000001 Carry
114 // E 6502 emulation mode
115 // B #$10 00010000 Break (emulation mode only)
116
117 void SetFlags(uint8_t val) {
118 status = val;
119 if (E) {
120 SetAccumulatorSize(true);
121 SetIndexSize(true);
122 SetSP(SP() & 0xFF | 0x100);
123 }
124 if (GetIndexSize()) {
125 X &= 0xff;
126 Y &= 0xff;
127 }
128 }
129
130 void SetZN(uint16_t value, bool byte) {
131 if (byte) {
132 SetZeroFlag((value & 0xff) == 0);
133 SetNegativeFlag(value & 0x80);
134 } else {
135 SetZeroFlag(value == 0);
136 SetNegativeFlag(value & 0x8000);
137 }
138 }
139
140 // Setting flags in the status register
141 bool m() { return GetAccumulatorSize() ? 1 : 0; }
142 bool xf() { return GetIndexSize() ? 1 : 0; }
143 int GetAccumulatorSize() const { return status & 0x20; }
144 int GetIndexSize() const { return status & 0x10; }
145 void SetAccumulatorSize(bool set) { SetFlag(0x20, set); }
146 void SetIndexSize(bool set) { SetFlag(0x10, set); }
147
148 // Set individual flags
149 void SetNegativeFlag(bool set) { SetFlag(0x80, set); }
150 void SetOverflowFlag(bool set) { SetFlag(0x40, set); }
151 void SetBreakFlag(bool set) { SetFlag(0x10, set); }
152 void SetDecimalFlag(bool set) { SetFlag(0x08, set); }
153 void SetInterruptFlag(bool set) { SetFlag(0x04, set); }
154 void SetZeroFlag(bool set) { SetFlag(0x02, set); }
155 void SetCarryFlag(bool set) { SetFlag(0x01, set); }
156
157 // Get individual flags
158 bool GetNegativeFlag() const { return GetFlag(0x80); }
159 bool GetOverflowFlag() const { return GetFlag(0x40); }
160 bool GetBreakFlag() const { return GetFlag(0x10); }
161 bool GetDecimalFlag() const { return GetFlag(0x08); }
162 bool GetInterruptFlag() const { return GetFlag(0x04); }
163 bool GetZeroFlag() const { return GetFlag(0x02); }
164 bool GetCarryFlag() const { return GetFlag(0x01); }
165
166 enum class AccessType { Control, Data };
167
168 uint8_t ReadOpcode() { return ReadByte((PB << 16) | PC++); }
169
170 uint16_t ReadOpcodeWord(bool int_check = false) {
171 uint8_t value = ReadOpcode();
172 if (int_check)
173 CheckInt();
174 return value | (ReadOpcode() << 8);
175 }
176
177 // Memory access routines
178 uint8_t ReadByte(uint32_t address) { return callbacks_.read_byte(address); }
179
180 // Read 16-bit value from consecutive addresses (little-endian)
181 uint16_t ReadWord(uint32_t address) {
182 uint8_t low = ReadByte(address);
183 uint8_t high = ReadByte(address + 1);
184 return low | (high << 8);
185 }
186
187 // Read 16-bit value from two separate addresses (for wrapping/crossing
188 // boundaries)
189 uint16_t ReadWord(uint32_t address, uint32_t address_high,
190 bool int_check = false) {
191 uint8_t value = ReadByte(address);
192 if (int_check)
193 CheckInt();
194 uint8_t value2 = ReadByte(address_high);
195 return value | (value2 << 8);
196 }
197 uint32_t ReadWordLong(uint32_t address) {
198 uint8_t value = ReadByte(address);
199 uint8_t value2 = ReadByte(address + 1);
200 uint8_t value3 = ReadByte(address + 2);
201 return value | (value2 << 8) | (value3 << 16);
202 }
203
204 void WriteByte(uint32_t address, uint8_t value) {
205 callbacks_.write_byte(address, value);
206 }
207
208 void WriteWord(uint32_t address, uint32_t address_high, uint16_t value,
209 bool reversed = false, bool int_check = false) {
210 if (reversed) {
211 callbacks_.write_byte(address_high, value >> 8);
212 if (int_check)
213 CheckInt();
214 callbacks_.write_byte(address, value & 0xFF);
215 } else {
216 callbacks_.write_byte(address, value & 0xFF);
217 if (int_check)
218 CheckInt();
219 callbacks_.write_byte(address_high, value >> 8);
220 }
221 }
222 void WriteLong(uint32_t address, uint32_t value) {
223 callbacks_.write_byte(address, value & 0xFF);
224 callbacks_.write_byte(address + 1, (value >> 8) & 0xFF);
225 callbacks_.write_byte(address + 2, value >> 16);
226 }
227
228 void PushByte(uint8_t value) {
229 callbacks_.write_byte(SP(), value);
230 SetSP(SP() - 1);
231 if (E)
232 SetSP((SP() & 0xff) | 0x100);
233 }
234 void PushWord(uint16_t value, bool int_check = false) {
235 PushByte(value >> 8);
236 if (int_check)
237 CheckInt();
238 PushByte(value & 0xFF);
239 }
240 void PushLong(uint32_t value) { // Push 24-bit value
241 PushByte(value >> 16);
242 PushWord(value & 0xFFFF);
243 }
244
245 uint8_t PopByte() {
246 SetSP(SP() + 1);
247 if (E)
248 SetSP((SP() & 0xff) | 0x100);
249 return ReadByte(SP());
250 }
251 uint16_t PopWord(bool int_check = false) {
252 uint8_t low = PopByte();
253 if (int_check)
254 CheckInt();
255 return low | (PopByte() << 8);
256 }
257 uint32_t PopLong() { // Pop 24-bit value
258 uint32_t low = PopWord();
259 uint32_t high = PopByte();
260 return (high << 16) | low;
261 }
262
263 void DoBranch(bool check) {
264 if (!check)
265 CheckInt();
266 uint8_t value = ReadOpcode();
267 if (check) {
268 CheckInt();
269 callbacks_.idle(false); // taken branch: 1 extra cycle
270 PC += (int8_t)value;
271 }
272 }
273
274 // Addressing Modes
275
276 // Effective Address:
277 // Bank: Data Bank Register if locating data
278 // Program Bank Register if transferring control
279 // High: Second operand byte
280 // Low: First operand byte
281 //
282 // LDA addr
283 uint32_t Absolute(uint32_t* low);
284
285 // Effective Address:
286 // The Data Bank Register is concatened with the 16-bit operand
287 // the 24-bit result is added to the X Index Register
288 // based on the emulation mode (16:X=0, 8:X=1)
289 //
290 // LDA addr, X
292 uint32_t AdrAbx(uint32_t* low, bool write);
293
294 // Effective Address:
295 // The Data Bank Register is concatened with the 16-bit operand
296 // the 24-bit result is added to the Y Index Register
297 // based on the emulation mode (16:Y=0, 8:Y=1)
298 //
299 // LDA addr, Y
301 uint32_t AdrAby(uint32_t* low, bool write);
302
303 void AdrImp();
304 uint32_t AdrIdx(uint32_t* low);
305
306 uint32_t AdrIdp(uint32_t* low);
307 uint32_t AdrIdy(uint32_t* low, bool write);
308 uint32_t AdrIdl(uint32_t* low);
309 uint32_t AdrIly(uint32_t* low);
310 uint32_t AdrIsy(uint32_t* low);
311 uint32_t Immediate(uint32_t* low, bool xFlag);
312
313 // Effective Address:
314 // Bank: Program Bank Register (PBR)
315 // High/low: The Indirect Address
316 // Indirect Address: Located in the Program Bank at the sum of
317 // the operand double byte and X based on the
318 // emulation mode
319 // JMP (addr, X)
321
322 // Effective Address:
323 // Bank: Program Bank Register (PBR)
324 // High/low: The Indirect Address
325 // Indirect Address: Located in Bank Zero, at the operand double byte
326 //
327 // JMP (addr)
329
330 // Effective Address:
331 // Bank/High/Low: The 24-bit Indirect Address
332 // Indirect Address: Located in Bank Zero, at the operand double byte
333 //
334 // JMP [addr]
336
337 // Effective Address:
338 // Bank: Third operand byte
339 // High: Second operand byte
340 // Low: First operand byte
341 //
342 // LDA long
343 uint32_t AbsoluteLong();
344 uint32_t AdrAbl(uint32_t* low);
345
346 // Effective Address:
347 // The 24-bit operand is added to X based on the emulation mode
348 //
349 // LDA long, X
351 uint32_t AdrAlx(uint32_t* low);
352
353 // Source Effective Address:
354 // Bank: Second operand byte
355 // High/Low: The 16-bit value in X, if X is 8-bit high byte is 0
356 //
357 // Destination Effective Address:
358 // Bank: First operand byte
359 // High/Low: The 16-bit value in Y, if Y is 8-bit high byte is 0
360 //
361 // Length:
362 // The number of bytes to be moved: 16-bit value in Acculumator C plus 1.
363 //
364 // MVN src, dst
365 void BlockMove(uint16_t source, uint16_t dest, uint16_t length);
366
367 // Effective Address:
368 // Bank: Zero
369 // High/low: Direct Page Register plus operand byte
370 //
371 // LDA dp
372 uint16_t DirectPage();
373 uint32_t AdrDp(uint32_t* low);
374
375 // Effective Address:
376 // Bank: Zero
377 // High/low: Direct Page Register plus operand byte plus X
378 // based on the emulation mode
379 //
380 // LDA dp, X
381 uint16_t DirectPageIndexedX();
382 uint32_t AdrDpx(uint32_t* low);
383
384 // Effective Address:
385 // Bank: Zero
386 // High/low: Direct Page Register plus operand byte plus Y
387 // based on the emulation mode
388 // LDA dp, Y
389 uint16_t DirectPageIndexedY();
390 uint32_t AdrDpy(uint32_t* low);
391
392 // Effective Address:
393 // Bank: Data bank register
394 // High/low: The indirect address
395 // Indirect Address: Located in the direct page at the sum of the direct page
396 // register, the operand byte, and X based on the emulation mode in bank zero.
397 //
398 // LDA (dp, X)
400
401 // Effective Address:
402 // Bank: Data bank register
403 // High/low: The 16-bit indirect address
404 // Indirect Address: The operand byte plus the direct page register in bank
405 // zero.
406 //
407 // LDA (dp)
409
410 // Effective Address:
411 // Bank/High/Low: The 24-bit indirect address
412 // Indirect address: The operand byte plus the direct page
413 // register in bank zero.
414 //
415 // LDA [dp]
416 uint32_t DirectPageIndirectLong();
417
418 // Effective Address:
419 // Found by concatenating the data bank to the double-byte
420 // indirect address, then adding Y based on the emulation mode.
421 //
422 // Indirect Address: Located in the Direct Page at the sum of the direct page
423 // register and the operand byte, in bank zero.
424 //
425 // LDA (dp), Y
427
428 // Effective Address:
429 // Found by adding to the triple-byte indirect address Y based on the
430 // emulation mode. Indrect Address: Located in the Direct Page at the sum
431 // of the direct page register and the operand byte in bank zero.
432 // Indirect Address:
433 // Located in the Direct Page at the sum of the direct page register and
434 // the operand byte in bank zero.
435 //
436 // LDA (dp), Y
438
439 // 8-bit data: Data Operand Byte
440 // 16-bit data 65816 native mode m or x = 0
441 // Data High: Second Operand Byte
442 // Data Low: First Operand Byte
443 //
444 // LDA #const
445 uint16_t Immediate(bool index_size = false);
446
447 uint16_t StackRelative();
448 uint32_t AdrSr(uint32_t* low);
449
450 // Effective Address:
451 // The Data Bank Register is concatenated to the Indirect Address;
452 // the 24-bit result is added to Y (16 bits if x = 0; else 8 bits)
453 // Indirect Address:
454 // Located at the 16-bit sum of the 8-bit operand and the 16-bit stack
455 // pointer
456 //
457 // LDA (sr, S), Y
459
460 // ======================================================
461 // Instructions
462
463 // ADC: Add with carry
464 void ADC(uint16_t operand);
465
466 // AND: Logical AND
467 void AND(uint32_t address, bool immediate = false);
468 void ANDAbsoluteLong(uint32_t address);
469
470 // ASL: Arithmetic shift left
471 void ASL(uint16_t address);
472
473 // BCC: Branch if carry clear
474 void BCC(int8_t offset);
475
476 // BCS: Branch if carry set
477 void BCS(int8_t offset);
478
479 // BEQ: Branch if equal
480 void BEQ(int8_t offset);
481
482 // BIT: Bit test
483 void BIT(uint16_t address);
484
485 // BMI: Branch if minus
486 void BMI(int8_t offset);
487
488 // BNE: Branch if not equal
489 void BNE(int8_t offset);
490
491 // BPL: Branch if plus
492 void BPL(int8_t offset);
493
494 // BRA: Branch always
495 void BRA(int8_t offset);
496
497 // BRK: Force interrupt
498 void BRK();
499
500 // BRL: Branch always long
501 void BRL(int16_t offset);
502
503 // BVC: Branch if overflow clear
504 void BVC(int8_t offset);
505
506 // BVS: Branch if overflow set
507 void BVS(int8_t offset);
508
509 // CLC: Clear carry flag
510 void CLC();
511
512 // CLD: Clear decimal mode
513 void CLD();
514
515 // CLI: Clear interrupt disable bit
516 void CLI();
517
518 // CLV: Clear overflow flag
519 void CLV();
520
521 // CMP: Compare
522 void CMP(uint32_t address, bool immediate = false);
523
524 // COP: Coprocessor enable
525 void COP();
526
527 // CPX: Compare X register
528 void CPX(uint32_t address, bool immediate = false);
529
530 // CPY: Compare Y register
531 void CPY(uint32_t address, bool immediate = false);
532
533 // DEC: Decrement memory
534 void DEC(uint32_t address, bool accumulator = false);
535
536 // DEX: Decrement X register
537 void DEX();
538
539 // DEY: Decrement Y register
540 void DEY();
541
542 // EOR: Exclusive OR
543 void EOR(uint32_t address, bool immediate = false);
544
545 // INC: Increment memory
546 void INC(uint32_t address, bool accumulator = false);
547
548 // INX: Increment X register
549 void INX();
550
551 // INY: Increment Y register
552 void INY();
553
554 // JMP: Jump
555 void JMP(uint16_t address);
556
557 // JML: Jump long
558 void JML(uint16_t address);
559
560 // JSR: Jump to subroutine
561 void JSR(uint16_t address);
562
563 // JSL: Jump to subroutine long
564 void JSL(uint16_t address);
565
566 // LDA: Load accumulator
567 void LDA(uint16_t address, bool immediate = false, bool direct_page = false,
568 bool data_bank = false);
569
570 // LDX: Load X register
571 void LDX(uint16_t address, bool immediate = false);
572
573 // LDY: Load Y register
574 void LDY(uint16_t address, bool immediate = false);
575
576 // LSR: Logical shift right
577 void LSR(uint16_t address, bool accumulator = false);
578
579 // MVN: Block move next
580 void MVN();
581
582 // MVP: Block move previous
583 void MVP();
584
585 // NOP: No operation
586 void NOP();
587
588 // ORA: Logical inclusive OR
589 void ORA(uint32_t low, uint32_t high);
590
591 // PEA: Push effective absolute address
592 void PEA();
593
594 // PEI: Push effective indirect address
595 void PEI();
596
597 // PER: Push effective relative address
598 void PER();
599
600 // PHA: Push accumulator
601 void PHA();
602
603 // PHB: Push data bank register
604 void PHB();
605
606 // PHD: Push direct page register
607 void PHD();
608
609 // PHK: Push program bank register
610 void PHK();
611
612 // PHP: Push processor status (flags)
613 void PHP();
614
615 // PHX: Push X register
616 void PHX();
617
618 // PHY: Push Y register
619 void PHY();
620
621 // PLA: Pull accumulator
622 void PLA();
623
624 // PLB: Pull data bank register
625 void PLB();
626
627 // PLD: Pull direct page register
628 void PLD();
629
630 // PLP: Pull processor status (flags)
631 void PLP();
632
633 // PLX: Pull X register
634 void PLX();
635
636 // PLY: Pull Y register
637 void PLY();
638
639 // REP: Reset processor status bits
640 void REP();
641
642 // ROL: Rotate left
643 void ROL(uint32_t address, bool accumulator = false);
644
645 // ROR: Rotate right
646 void ROR(uint32_t address, bool accumulator = false);
647
648 // RTI: Return from interrupt
649 void RTI();
650
651 // RTL: Return from subroutine long
652 void RTL();
653
654 // RTS: Return from subroutine
655 void RTS();
656
657 // SBC: Subtract with carry
658 void SBC(uint32_t operand, bool immediate = false);
659
660 // SEC: Set carry flag
661 void SEC();
662
663 // SED: Set decimal mode
664 void SED();
665
666 // SEI: Set interrupt disable status
667 void SEI();
668
669 // SEP: Set processor status bits
670 void SEP();
671
672 // STA: Store accumulator
673 void STA(uint32_t address);
674
675 // STP: Stop the processor
676 void STP();
677
678 // STX: Store X register
679 void STX(uint16_t address);
680
681 // STY: Store Y register
682 void STY(uint16_t address);
683
684 // STZ: Store zero
685 void STZ(uint16_t address);
686
687 // TAX: Transfer accumulator to X
688 void TAX();
689
690 // TAY: Transfer accumulator to Y
691 void TAY();
692
693 // TCD: Transfer 16-bit accumulator to direct page register
694 void TCD();
695
696 // TCS: Transfer 16-bit accumulator to stack pointer
697 void TCS();
698
699 // TDC: Transfer direct page register to 16-bit accumulator
700 void TDC();
701
702 // TRB: Test and reset bits
703 void TRB(uint16_t address);
704
705 // TSB: Test and set bits
706 void TSB(uint16_t address);
707
708 // TSC: Transfer stack pointer to 16-bit accumulator
709 void TSC();
710
711 // TSX: Transfer stack pointer to X
712 void TSX();
713
714 // TXA: Transfer X to accumulator
715 void TXA();
716
717 // TXS: Transfer X to stack pointer
718 void TXS();
719
720 // TXY: Transfer X to Y
721 void TXY();
722
723 // TYA: Transfer Y to accumulator
724 void TYA();
725
726 // TYX: Transfer Y to X
727 void TYX();
728
729 // WAI: Wait for interrupt
730 void WAI();
731
732 // WDM: Reserved for future expansion
733 void WDM();
734
735 // XBA: Exchange B and A
736 void XBA();
737
738 // XCE: Exchange carry and emulation bits
739 void XCE();
740
741 void And(uint32_t low, uint32_t high);
742 void Eor(uint32_t low, uint32_t high);
743 void Adc(uint32_t low, uint32_t high);
744 void Sbc(uint32_t low, uint32_t high);
745 void Cmp(uint32_t low, uint32_t high);
746 void Cpx(uint32_t low, uint32_t high);
747 void Cpy(uint32_t low, uint32_t high);
748 void Bit(uint32_t low, uint32_t high);
749 void Lda(uint32_t low, uint32_t high);
750 void Ldx(uint32_t low, uint32_t high);
751 void Ldy(uint32_t low, uint32_t high);
752 void Sta(uint32_t low, uint32_t high);
753 void Stx(uint32_t low, uint32_t high);
754 void Sty(uint32_t low, uint32_t high);
755 void Stz(uint32_t low, uint32_t high);
756 void Ror(uint32_t low, uint32_t high);
757 void Rol(uint32_t low, uint32_t high);
758 void Lsr(uint32_t low, uint32_t high);
759 void Asl(uint32_t low, uint32_t high);
760 void Inc(uint32_t low, uint32_t high);
761 void Dec(uint32_t low, uint32_t high);
762 void Tsb(uint32_t low, uint32_t high);
763 void Trb(uint32_t low, uint32_t high);
764
765 uint16_t SP() const { return memory.SP(); }
766 void SetSP(uint16_t value) { memory.SetSP(value); }
767
768 bool IsBreakpoint(uint32_t address) {
769 return std::find(breakpoints_.begin(), breakpoints_.end(), address) !=
770 breakpoints_.end();
771 }
772 void SetBreakpoint(uint32_t address) { breakpoints_.push_back(address); }
773 void ClearBreakpoint(uint32_t address) {
774 breakpoints_.erase(
775 std::remove(breakpoints_.begin(), breakpoints_.end(), address),
776 breakpoints_.end());
777 }
779 breakpoints_.clear();
780 breakpoints_.shrink_to_fit();
781 }
782 auto GetBreakpoints() { return breakpoints_; }
783
784 void CheckInt() {
787 int_delay_ = false;
788 }
789
790 bool stopped() const { return stopped_; }
791
792 // REMOVED: SetInstructionLogging - DisassemblyViewer is always active
793 // Use disassembly_viewer().SetRecording(bool) for runtime control
794
795 private:
796 void compare(uint16_t register_value, uint16_t memory_value) {
797 uint16_t result;
798 if (GetIndexSize()) {
799 // 8-bit mode
800 uint8_t result8 = static_cast<uint8_t>(register_value) -
801 static_cast<uint8_t>(memory_value);
802 result = result8;
803 SetNegativeFlag(result & 0x80); // Negative flag for 8-bit
804 } else {
805 // 16-bit mode
806 result = register_value - memory_value;
807 SetNegativeFlag(result & 0x8000); // Negative flag for 16-bit
808 }
809 SetZeroFlag(result == 0); // Zero flag
810 SetCarryFlag(register_value >= memory_value); // Carry flag
811 }
812
813 void SetFlag(uint8_t mask, bool set) {
814 if (set) {
815 status |= mask; // Set the bit
816 } else {
817 status &= ~mask; // Clear the bit
818 }
819 }
820
821 bool GetFlag(uint8_t mask) const { return (status & mask) != 0; }
822
823 // REMOVED: log_instructions_ flag - no longer needed
824
825 bool waiting_ = false;
826 bool stopped_ = false;
827
828 bool irq_wanted_ = false;
829 bool nmi_wanted_ = false;
830 bool reset_wanted_ = false;
831 bool int_wanted_ = false;
832 bool int_delay_ = false;
833
836};
837
838} // namespace emu
839} // namespace yaze
840
841#endif // YAZE_APP_EMU_CPU_H_
const auto & callbacks() const
Definition cpu.h:46
uint16_t SP() const
Definition cpu.h:765
uint16_t D
Definition cpu.h:77
void Stx(uint32_t low, uint32_t high)
debug::DisassemblyViewer & disassembly_viewer()
Definition cpu.cc:19
uint8_t status
Definition cpu.h:81
void BRA(int8_t offset)
bool GetNegativeFlag() const
Definition cpu.h:158
uint32_t AdrAby(uint32_t *low, bool write)
void WriteWord(uint32_t address, uint32_t address_high, uint16_t value, bool reversed=false, bool int_check=false)
Definition cpu.h:208
uint16_t DirectPage()
void JML(uint16_t address)
uint32_t DirectPageIndirectLongIndexedY()
void BVC(int8_t offset)
bool GetInterruptFlag() const
Definition cpu.h:162
std::function< void(uint32_t address, uint8_t opcode, const std::vector< uint8_t > &operands, const std::string &mnemonic, const std::string &operand_str) on_instruction_executed_)
Definition cpu.h:71
uint32_t AdrAbl(uint32_t *low)
void JSR(uint16_t address)
void Asl(uint32_t low, uint32_t high)
void STA(uint32_t address)
uint32_t AdrIdy(uint32_t *low, bool write)
Definition addressing.cc:55
void Inc(uint32_t low, uint32_t high)
Cpu(Memory &mem)
Definition cpu.h:39
bool stopped_
Definition cpu.h:826
uint16_t DirectPageIndirectIndexedY()
uint8_t DB
Definition cpu.h:78
void SBC(uint32_t operand, bool immediate=false)
uint32_t AdrSr(uint32_t *low)
Definition addressing.cc:87
bool stopped() const
Definition cpu.h:790
void SetZN(uint16_t value, bool byte)
Definition cpu.h:130
void Ldy(uint32_t low, uint32_t high)
uint32_t Immediate(uint32_t *low, bool xFlag)
Definition addressing.cc:18
uint16_t ReadWord(uint32_t address)
Definition cpu.h:181
void LSR(uint16_t address, bool accumulator=false)
uint16_t X
Definition cpu.h:75
uint16_t DirectPageIndexedY()
uint16_t AbsoluteIndexedIndirect()
void Sta(uint32_t low, uint32_t high)
uint8_t ReadByte(uint32_t address)
Definition cpu.h:178
uint32_t AdrIdl(uint32_t *low)
Definition addressing.cc:67
void SetIrq(bool state)
Definition cpu.h:54
void BlockMove(uint16_t source, uint16_t dest, uint16_t length)
uint32_t AbsoluteLongIndexedX()
uint32_t DirectPageIndirectLong()
bool GetFlag(uint8_t mask) const
Definition cpu.h:821
void Cpy(uint32_t low, uint32_t high)
uint16_t ReadWord(uint32_t address, uint32_t address_high, bool int_check=false)
Definition cpu.h:189
void SetDecimalFlag(bool set)
Definition cpu.h:152
uint16_t Y
Definition cpu.h:76
void Nmi()
Definition cpu.h:55
uint8_t ReadOpcode()
Definition cpu.h:168
bool GetZeroFlag() const
Definition cpu.h:163
uint32_t AdrAbx(uint32_t *low, bool write)
void STY(uint16_t address)
void CheckInt()
Definition cpu.h:784
void SaveState(std::ostream &stream)
Definition cpu.cc:2031
void CPX(uint32_t address, bool immediate=false)
uint32_t AdrDp(uint32_t *low)
void Bit(uint32_t low, uint32_t high)
void set_int_delay(bool delay)
Definition cpu.h:84
std::function< bool(uint32_t pc)> on_breakpoint_hit_
Definition cpu.h:65
uint32_t PopLong()
Definition cpu.h:257
void LoadState(std::istream &stream)
Definition cpu.cc:2062
bool waiting_
Definition cpu.h:825
int GetIndexSize() const
Definition cpu.h:144
Memory & memory
Definition cpu.h:834
void And(uint32_t low, uint32_t high)
void SetZeroFlag(bool set)
Definition cpu.h:154
void WriteByte(uint32_t address, uint8_t value)
Definition cpu.h:204
bool reset_wanted_
Definition cpu.h:830
void INC(uint32_t address, bool accumulator=false)
void BCC(int8_t offset)
uint16_t PC
Definition cpu.h:80
void ORA(uint32_t low, uint32_t high)
void BNE(int8_t offset)
uint16_t A
Definition cpu.h:74
uint32_t AdrIdp(uint32_t *low)
Definition addressing.cc:46
void Sbc(uint32_t low, uint32_t high)
void CMP(uint32_t address, bool immediate=false)
void Trb(uint32_t low, uint32_t high)
void Lda(uint32_t low, uint32_t high)
void Cpx(uint32_t low, uint32_t high)
void EOR(uint32_t address, bool immediate=false)
void Rol(uint32_t low, uint32_t high)
uint32_t AdrDpy(uint32_t *low)
Definition addressing.cc:37
void ASL(uint16_t address)
uint8_t PB
Definition cpu.h:79
void Tsb(uint32_t low, uint32_t high)
void BMI(int8_t offset)
void Dec(uint32_t low, uint32_t high)
void SetAccumulatorSize(bool set)
Definition cpu.h:145
void TRB(uint16_t address)
void SetFlag(uint8_t mask, bool set)
Definition cpu.h:813
void SetFlags(uint8_t val)
Definition cpu.h:117
void DoInterrupt()
Definition cpu.cc:253
void TSB(uint16_t address)
auto GetBreakpoints()
Definition cpu.h:782
void Ldx(uint32_t low, uint32_t high)
uint16_t DirectPageIndexedX()
uint16_t Immediate(bool index_size=false)
void ADC(uint16_t operand)
void BRL(int16_t offset)
uint32_t AbsoluteIndexedY()
void ROL(uint32_t address, bool accumulator=false)
void PushByte(uint8_t value)
Definition cpu.h:228
uint32_t AbsoluteLong()
void PushWord(uint16_t value, bool int_check=false)
Definition cpu.h:234
int GetAccumulatorSize() const
Definition cpu.h:143
void AND(uint32_t address, bool immediate=false)
uint32_t AdrIly(uint32_t *low)
Definition addressing.cc:77
void STX(uint16_t address)
void ROR(uint32_t address, bool accumulator=false)
void LogInstructions(uint16_t PC, uint8_t opcode, uint16_t operand, bool immediate, bool accumulator_mode)
Definition cpu.cc:1990
void SetOverflowFlag(bool set)
Definition cpu.h:150
void ExecuteInstruction(uint8_t opcode)
Definition cpu.cc:270
uint16_t DirectPageIndexedIndirectX()
uint32_t ReadWordLong(uint32_t address)
Definition cpu.h:197
uint32_t AdrIdx(uint32_t *low)
void BEQ(int8_t offset)
uint32_t Absolute(uint32_t *low)
uint32_t AdrAlx(uint32_t *low)
void Reset(bool hard=false)
Definition cpu.cc:34
uint16_t PopWord(bool int_check=false)
Definition cpu.h:251
void ClearBreakpoint(uint32_t address)
Definition cpu.h:773
void STZ(uint16_t address)
uint16_t DirectPageIndirect()
void BCS(int8_t offset)
void SetCarryFlag(bool set)
Definition cpu.h:155
void SetInterruptFlag(bool set)
Definition cpu.h:153
bool GetCarryFlag() const
Definition cpu.h:164
void SetBreakpoint(uint32_t address)
Definition cpu.h:772
bool IsBreakpoint(uint32_t address)
Definition cpu.h:768
bool m()
Definition cpu.h:141
bool irq_wanted_
Definition cpu.h:828
void RunOpcode()
Definition cpu.cc:56
CpuCallbacks callbacks_
Definition cpu.h:835
void CPY(uint32_t address, bool immediate=false)
void DoBranch(bool check)
Definition cpu.h:263
void Eor(uint32_t low, uint32_t high)
void SetSP(uint16_t value)
Definition cpu.h:766
uint32_t AdrIsy(uint32_t *low)
Definition addressing.cc:94
auto & callbacks()
Definition cpu.h:45
void ANDAbsoluteLong(uint32_t address)
void DEC(uint32_t address, bool accumulator=false)
void BVS(int8_t offset)
bool int_delay_
Definition cpu.h:832
void PushLong(uint32_t value)
Definition cpu.h:240
debug::DisassemblyViewer * disassembly_viewer_
Definition cpu.h:86
void Stz(uint32_t low, uint32_t high)
void ClearBreakpoints()
Definition cpu.h:778
bool GetBreakFlag() const
Definition cpu.h:160
bool GetDecimalFlag() const
Definition cpu.h:161
uint16_t AbsoluteIndirect()
void Cmp(uint32_t low, uint32_t high)
uint8_t PopByte()
Definition cpu.h:245
std::vector< uint32_t > breakpoints_
Definition cpu.h:57
uint32_t AbsoluteIndexedX()
void BIT(uint16_t address)
uint16_t ReadOpcodeWord(bool int_check=false)
Definition cpu.h:170
void BPL(int8_t offset)
uint8_t E
Definition cpu.h:103
uint16_t StackRelative()
void Ror(uint32_t low, uint32_t high)
bool GetOverflowFlag() const
Definition cpu.h:159
void SetNegativeFlag(bool set)
Definition cpu.h:149
void SetBreakFlag(bool set)
Definition cpu.h:151
bool int_wanted_
Definition cpu.h:831
uint32_t StackRelativeIndirectIndexedY()
void JMP(uint16_t address)
void Sty(uint32_t low, uint32_t high)
bool nmi_wanted_
Definition cpu.h:829
void LDX(uint16_t address, bool immediate=false)
void JSL(uint16_t address)
void Lsr(uint32_t low, uint32_t high)
uint32_t AdrDpx(uint32_t *low)
Definition addressing.cc:28
void compare(uint16_t register_value, uint16_t memory_value)
Definition cpu.h:796
void SetIndexSize(bool set)
Definition cpu.h:146
uint32_t AbsoluteIndirectLong()
void Adc(uint32_t low, uint32_t high)
void LDA(uint16_t address, bool immediate=false, bool direct_page=false, bool data_bank=false)
void WriteLong(uint32_t address, uint32_t value)
Definition cpu.h:222
void LDY(uint16_t address, bool immediate=false)
bool xf()
Definition cpu.h:142
InstructionEntry(uint32_t addr, uint8_t op, const std::string &ops, const std::string &instr)
Definition cpu.h:21
std::string instruction
Definition cpu.h:34
uint32_t GetAddress() const
Definition cpu.h:26
const std::string & GetInstruction() const
Definition cpu.h:29
uint8_t GetOpcode() const
Definition cpu.h:27
const std::string & GetOperands() const
Definition cpu.h:28
std::string operands
Definition cpu.h:33
Memory interface.
Definition memory.h:64
virtual uint16_t SP() const =0
virtual void SetSP(uint16_t value)=0
Advanced disassembly viewer with sparse storage and interactive features.
std::function< void(bool waiting)> idle
Definition memory.h:53
std::function< uint8_t(uint32_t)> read_byte
Definition memory.h:51
std::function< void(uint32_t, uint8_t)> write_byte
Definition memory.h:52