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