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