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