dg6502/
cpu.rs

1use std::fmt::Display;
2
3use crate::bus;
4
5const LOOKUP_TABLE: [(Instruction, AddressMode); 256] = [
6    (Instruction::BRK, AddressMode::Implied),  (Instruction::ORA, AddressMode::IndirectXIndex), (Instruction::JAM, AddressMode::Accumulator),   (Instruction::SLO, AddressMode::IndirectXIndex), (Instruction::NOP, AddressMode::Zeropage), (Instruction::ORA, AddressMode::Zeropage), (Instruction::ASL, AddressMode::Zeropage), (Instruction::SLO, AddressMode::Zeropage), (Instruction::PHP, AddressMode::Implied), (Instruction::ORA, AddressMode::Immediate), (Instruction::ASL, AddressMode::Accumulator), (Instruction::ANC, AddressMode::Immediate), (Instruction::NOP, AddressMode::Absolute), (Instruction::ORA, AddressMode::Absolute), (Instruction::ASL, AddressMode::Absolute), (Instruction::SLO, AddressMode::Absolute),
7    (Instruction::BPL, AddressMode::Relative), (Instruction::ORA, AddressMode::IndirectYIndex), (Instruction::JAM, AddressMode::Accumulator),   (Instruction::SLO, AddressMode::IndirectYIndex), (Instruction::NOP, AddressMode::ZeropageXIndex), (Instruction::ORA, AddressMode::ZeropageXIndex), (Instruction::ASL, AddressMode::ZeropageXIndex), (Instruction::SLO, AddressMode::ZeropageXIndex), (Instruction::CLC, AddressMode::Implied), (Instruction::ORA, AddressMode::AbsoluteYIndex), (Instruction::NOP, AddressMode::Implied), (Instruction::SLO, AddressMode::AbsoluteYIndex), (Instruction::NOP, AddressMode::AbsoluteXIndex), (Instruction::ORA, AddressMode::AbsoluteXIndex), (Instruction::ASL, AddressMode::AbsoluteXIndex), (Instruction::SLO, AddressMode::AbsoluteXIndex),
8    (Instruction::JSR, AddressMode::Absolute), (Instruction::AND, AddressMode::IndirectXIndex), (Instruction::JAM, AddressMode::Accumulator),   (Instruction::RLA, AddressMode::IndirectXIndex), (Instruction::BIT, AddressMode::Zeropage), (Instruction::AND, AddressMode::Zeropage), (Instruction::ROL, AddressMode::Zeropage),                   (Instruction::RLA, AddressMode::Zeropage), (Instruction::PLP, AddressMode::Implied), (Instruction::AND, AddressMode::Immediate), (Instruction::ROL, AddressMode::Accumulator), (Instruction::ANC, AddressMode::Immediate), (Instruction::BIT, AddressMode::Absolute), (Instruction::AND, AddressMode::Absolute), (Instruction::ROL, AddressMode::Absolute), (Instruction::RLA, AddressMode::Absolute),
9    (Instruction::BMI, AddressMode::Relative), (Instruction::AND, AddressMode::IndirectYIndex), (Instruction::JAM, AddressMode::Accumulator),   (Instruction::RLA, AddressMode::IndirectYIndex), (Instruction::NOP, AddressMode::ZeropageXIndex), (Instruction::AND, AddressMode::ZeropageXIndex), (Instruction::ROL, AddressMode::ZeropageXIndex), (Instruction::RLA, AddressMode::ZeropageXIndex), (Instruction::SEC, AddressMode::Implied), (Instruction::AND, AddressMode::AbsoluteYIndex), (Instruction::NOP, AddressMode::Implied), (Instruction::RLA, AddressMode::AbsoluteYIndex), (Instruction::NOP, AddressMode::AbsoluteXIndex), (Instruction::AND, AddressMode::AbsoluteXIndex), (Instruction::ROL, AddressMode::AbsoluteXIndex), (Instruction::RLA, AddressMode::AbsoluteXIndex),
10    (Instruction::RTI, AddressMode::Implied),  (Instruction::EOR, AddressMode::IndirectXIndex), (Instruction::JAM, AddressMode::Accumulator),   (Instruction::SRE, AddressMode::IndirectXIndex), (Instruction::NOP, AddressMode::Zeropage), (Instruction::EOR, AddressMode::Zeropage), (Instruction::LSR, AddressMode::Zeropage),                     (Instruction::SRE, AddressMode::Zeropage), (Instruction::PHA, AddressMode::Implied), (Instruction::EOR, AddressMode::Immediate), (Instruction::LSR, AddressMode::Accumulator), (Instruction::ALR, AddressMode::Immediate), (Instruction::JMP, AddressMode::Absolute), (Instruction::EOR, AddressMode::Absolute), (Instruction::LSR, AddressMode::Absolute), (Instruction::SRE, AddressMode::Absolute),
11    (Instruction::BVC, AddressMode::Relative), (Instruction::EOR, AddressMode::IndirectYIndex), (Instruction::JAM, AddressMode::Accumulator),   (Instruction::SRE, AddressMode::IndirectYIndex), (Instruction::NOP, AddressMode::ZeropageXIndex), (Instruction::EOR, AddressMode::ZeropageXIndex), (Instruction::LSR, AddressMode::ZeropageXIndex), (Instruction::SRE, AddressMode::ZeropageXIndex), (Instruction::CLI, AddressMode::Implied), (Instruction::EOR, AddressMode::AbsoluteYIndex), (Instruction::NOP, AddressMode::Implied), (Instruction::SRE, AddressMode::AbsoluteYIndex), (Instruction::NOP, AddressMode::AbsoluteXIndex), (Instruction::EOR, AddressMode::AbsoluteXIndex), (Instruction::LSR, AddressMode::AbsoluteXIndex), (Instruction::SRE, AddressMode::AbsoluteXIndex),
12    (Instruction::RTS, AddressMode::Implied),  (Instruction::ADC, AddressMode::IndirectXIndex), (Instruction::JAM, AddressMode::Accumulator),   (Instruction::RRA, AddressMode::IndirectXIndex), (Instruction::NOP, AddressMode::Zeropage), (Instruction::ADC, AddressMode::Zeropage), (Instruction::ROR, AddressMode::Zeropage),                     (Instruction::RRA, AddressMode::Zeropage), (Instruction::PLA, AddressMode::Implied), (Instruction::ADC, AddressMode::Immediate), (Instruction::ROR, AddressMode::Accumulator), (Instruction::ARR, AddressMode::Immediate), (Instruction::JMP, AddressMode::Indirect), (Instruction::ADC, AddressMode::Absolute), (Instruction::ROR, AddressMode::Absolute), (Instruction::RRA, AddressMode::Absolute),
13    (Instruction::BVS, AddressMode::Relative), (Instruction::ADC, AddressMode::IndirectYIndex), (Instruction::JAM, AddressMode::Accumulator),   (Instruction::RRA, AddressMode::IndirectYIndex), (Instruction::NOP, AddressMode::ZeropageXIndex), (Instruction::ADC, AddressMode::ZeropageXIndex), (Instruction::ROR, AddressMode::ZeropageXIndex), (Instruction::RRA, AddressMode::ZeropageXIndex), (Instruction::SEI, AddressMode::Implied), (Instruction::ADC, AddressMode::AbsoluteYIndex), (Instruction::NOP, AddressMode::Implied), (Instruction::RRA, AddressMode::AbsoluteYIndex), (Instruction::NOP, AddressMode::AbsoluteXIndex), (Instruction::ADC, AddressMode::AbsoluteXIndex), (Instruction::ROR, AddressMode::AbsoluteXIndex), (Instruction::RRA, AddressMode::AbsoluteXIndex),
14    (Instruction::NOP, AddressMode::Immediate),(Instruction::STA, AddressMode::IndirectXIndex), (Instruction::NOP, AddressMode::Immediate),     (Instruction::SAX, AddressMode::IndirectXIndex), (Instruction::STY, AddressMode::Zeropage), (Instruction::STA, AddressMode::Zeropage), (Instruction::STX, AddressMode::Zeropage),                (Instruction::SAX, AddressMode::Zeropage), (Instruction::DEY, AddressMode::Implied), (Instruction::NOP, AddressMode::Immediate), (Instruction::TXA, AddressMode::Implied), (Instruction::ANE, AddressMode::Immediate), (Instruction::STY, AddressMode::Absolute), (Instruction::STA, AddressMode::Absolute), (Instruction::STX, AddressMode::Absolute), (Instruction::SAX, AddressMode::Absolute),
15    (Instruction::BCC, AddressMode::Relative), (Instruction::STA, AddressMode::IndirectYIndex), (Instruction::JAM, AddressMode::Accumulator),   (Instruction::SHA, AddressMode::IndirectYIndex), (Instruction::STY, AddressMode::ZeropageXIndex), (Instruction::STA, AddressMode::ZeropageXIndex), (Instruction::STX, AddressMode::ZeropageYIndex), (Instruction::SAX, AddressMode::ZeropageYIndex), (Instruction::TYA, AddressMode::Implied), (Instruction::STA, AddressMode::AbsoluteYIndex), (Instruction::TXS, AddressMode::Implied), (Instruction::TAS, AddressMode::AbsoluteYIndex), (Instruction::SHY, AddressMode::AbsoluteXIndex), (Instruction::STA, AddressMode::AbsoluteXIndex), (Instruction::SHX, AddressMode::AbsoluteXIndex), (Instruction::SHA, AddressMode::AbsoluteYIndex),
16    (Instruction::LDY, AddressMode::Immediate),(Instruction::LDA, AddressMode::IndirectXIndex), (Instruction::LDX, AddressMode::Immediate),     (Instruction::LAX, AddressMode::IndirectXIndex), (Instruction::LDY, AddressMode::Zeropage), (Instruction::LDA, AddressMode::Zeropage), (Instruction::LDX, AddressMode::Zeropage),                    (Instruction::LAX, AddressMode::Zeropage), (Instruction::TAY, AddressMode::Implied), (Instruction::LDA, AddressMode::Immediate), (Instruction::TAX, AddressMode::Implied), (Instruction::LXA, AddressMode::Immediate), (Instruction::LDY, AddressMode::Absolute), (Instruction::LDA, AddressMode::Absolute), (Instruction::LDX, AddressMode::Absolute), (Instruction::LAX, AddressMode::Absolute),
17    (Instruction::BCS, AddressMode::Relative), (Instruction::LDA, AddressMode::IndirectYIndex), (Instruction::JAM, AddressMode::Accumulator),(Instruction::LAX, AddressMode::IndirectYIndex), (Instruction::LDY, AddressMode::ZeropageXIndex), (Instruction::LDA, AddressMode::ZeropageXIndex), (Instruction::LDX, AddressMode::ZeropageYIndex), (Instruction::LAX, AddressMode::ZeropageYIndex), (Instruction::CLV, AddressMode::Implied), (Instruction::LDA, AddressMode::AbsoluteYIndex), (Instruction::TSX, AddressMode::Implied), (Instruction::LAS, AddressMode::AbsoluteYIndex), (Instruction::LDY, AddressMode::AbsoluteXIndex), (Instruction::LDA, AddressMode::AbsoluteXIndex), (Instruction::LDX, AddressMode::AbsoluteYIndex), (Instruction::LAX, AddressMode::AbsoluteYIndex),
18    (Instruction::CPY, AddressMode::Immediate),(Instruction::CMP, AddressMode::IndirectXIndex), (Instruction::NOP, AddressMode::Immediate),       (Instruction::DCP, AddressMode::IndirectXIndex), (Instruction::CPY, AddressMode::Zeropage), (Instruction::CMP, AddressMode::Zeropage), (Instruction::DEC, AddressMode::Zeropage),                    (Instruction::DCP, AddressMode::Zeropage), (Instruction::INY, AddressMode::Implied), (Instruction::CMP, AddressMode::Immediate), (Instruction::DEX, AddressMode::Implied), (Instruction::SBX, AddressMode::Immediate), (Instruction::CPY, AddressMode::Absolute), (Instruction::CMP, AddressMode::Absolute), (Instruction::DEC, AddressMode::Absolute), (Instruction::DCP, AddressMode::Absolute),
19    (Instruction::BNE, AddressMode::Relative), (Instruction::CMP, AddressMode::IndirectYIndex), (Instruction::JAM, AddressMode::Accumulator),   (Instruction::DCP, AddressMode::IndirectYIndex), (Instruction::NOP, AddressMode::ZeropageXIndex), (Instruction::CMP, AddressMode::ZeropageXIndex), (Instruction::DEC, AddressMode::ZeropageXIndex), (Instruction::DCP, AddressMode::ZeropageXIndex), (Instruction::CLD, AddressMode::Implied), (Instruction::CMP, AddressMode::AbsoluteYIndex), (Instruction::NOP, AddressMode::Implied), (Instruction::DCP, AddressMode::AbsoluteXIndex), (Instruction::NOP, AddressMode::AbsoluteXIndex), (Instruction::CMP, AddressMode::AbsoluteXIndex), (Instruction::DEC, AddressMode::AbsoluteXIndex), (Instruction::DCP, AddressMode::AbsoluteXIndex),
20    (Instruction::CPX, AddressMode::Immediate),(Instruction::SBC, AddressMode::IndirectXIndex), (Instruction::NOP, AddressMode::Immediate),       (Instruction::ISC, AddressMode::IndirectXIndex), (Instruction::CPX, AddressMode::Zeropage), (Instruction::SBC, AddressMode::Zeropage), (Instruction::INC, AddressMode::Zeropage),                    (Instruction::ISC, AddressMode::Zeropage), (Instruction::INX, AddressMode::Implied), (Instruction::SBC, AddressMode::Immediate), (Instruction::NOP, AddressMode::Implied), (Instruction::USBC, AddressMode::Immediate), (Instruction::CPX, AddressMode::Absolute), (Instruction::SBC, AddressMode::Absolute), (Instruction::INC, AddressMode::Absolute), (Instruction::ISC, AddressMode::Absolute),
21    (Instruction::BEQ, AddressMode::Relative), (Instruction::SBC, AddressMode::IndirectYIndex), (Instruction::JAM, AddressMode::Accumulator),   (Instruction::ISC, AddressMode::IndirectYIndex), (Instruction::NOP, AddressMode::ZeropageXIndex), (Instruction::SBC, AddressMode::ZeropageXIndex), (Instruction::INC, AddressMode::ZeropageXIndex), (Instruction::ISC, AddressMode::ZeropageXIndex), (Instruction::SED, AddressMode::Implied), (Instruction::SBC, AddressMode::AbsoluteYIndex), (Instruction::NOP, AddressMode::Implied), (Instruction::ISC, AddressMode::AbsoluteXIndex), (Instruction::NOP, AddressMode::AbsoluteXIndex), (Instruction::SBC, AddressMode::AbsoluteXIndex), (Instruction::INC, AddressMode::AbsoluteXIndex), (Instruction::ISC, AddressMode::AbsoluteXIndex)
22];
23
24const CYCLE_TIMES: [(u8, CycleAddition); 256] = [
25    (7, CycleAddition::None), (6, CycleAddition::None), (0, CycleAddition::None), (8, CycleAddition::None), (3, CycleAddition::None), (3, CycleAddition::None), (5, CycleAddition::None), (5, CycleAddition::None), (3, CycleAddition::None), (2, CycleAddition::None), (2, CycleAddition::None), (2, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), (6, CycleAddition::None), (6, CycleAddition::None), 
26    (2, CycleAddition::BranchOnPage), (5, CycleAddition::PageBoundaryCrossed), (0, CycleAddition::None), (8, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), (6, CycleAddition::None), (6, CycleAddition::None), (2, CycleAddition::None), (4, CycleAddition::PageBoundaryCrossed), (2, CycleAddition::None), (7, CycleAddition::None), (4, CycleAddition::PageBoundaryCrossed), (4, CycleAddition::PageBoundaryCrossed), (7, CycleAddition::None), (7, CycleAddition::None), 
27    (6, CycleAddition::None), (6, CycleAddition::None), (0, CycleAddition::None), (8, CycleAddition::None), (3, CycleAddition::None), (3, CycleAddition::None), (5, CycleAddition::None), (5, CycleAddition::None), (4, CycleAddition::None), (2, CycleAddition::None), (2, CycleAddition::None), (2, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), (6, CycleAddition::None), (6, CycleAddition::None), 
28    (2, CycleAddition::BranchOnPage), (5, CycleAddition::PageBoundaryCrossed), (0, CycleAddition::None), (8, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), (6, CycleAddition::None), (6, CycleAddition::None), (2, CycleAddition::None), (4, CycleAddition::PageBoundaryCrossed), (2, CycleAddition::None), (7, CycleAddition::None), (4, CycleAddition::PageBoundaryCrossed), (4, CycleAddition::PageBoundaryCrossed), (7, CycleAddition::None), (7, CycleAddition::None), 
29    (6, CycleAddition::None), (6, CycleAddition::None), (0, CycleAddition::None), (8, CycleAddition::None), (3, CycleAddition::None), (3, CycleAddition::None), (5, CycleAddition::None), (5, CycleAddition::None), (3, CycleAddition::None), (2, CycleAddition::None), (2, CycleAddition::None), (2, CycleAddition::None), (3, CycleAddition::None), (4, CycleAddition::None), (6, CycleAddition::None), (6, CycleAddition::None), 
30    (2, CycleAddition::BranchOnPage), (5, CycleAddition::PageBoundaryCrossed), (0, CycleAddition::None), (8, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), (6, CycleAddition::None), (6, CycleAddition::None), (2, CycleAddition::None), (4, CycleAddition::PageBoundaryCrossed), (2, CycleAddition::None), (7, CycleAddition::None), (4, CycleAddition::PageBoundaryCrossed), (4, CycleAddition::PageBoundaryCrossed), (7, CycleAddition::None), (7, CycleAddition::None), 
31    (6, CycleAddition::None), (6, CycleAddition::None), (0, CycleAddition::None), (8, CycleAddition::None), (3, CycleAddition::None), (3, CycleAddition::None), (5, CycleAddition::None), (5, CycleAddition::None), (4, CycleAddition::None), (2, CycleAddition::None), (2, CycleAddition::None), (2, CycleAddition::None), (5, CycleAddition::None), (4, CycleAddition::None), (6, CycleAddition::None), (6, CycleAddition::None), 
32    (2, CycleAddition::BranchOnPage), (5, CycleAddition::PageBoundaryCrossed), (0, CycleAddition::None), (8, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), (6, CycleAddition::None), (6, CycleAddition::None), (2, CycleAddition::None), (4, CycleAddition::PageBoundaryCrossed), (2, CycleAddition::None), (7, CycleAddition::None), (4, CycleAddition::PageBoundaryCrossed), (4, CycleAddition::PageBoundaryCrossed), (7, CycleAddition::None), (7, CycleAddition::None), 
33    (2, CycleAddition::None), (6, CycleAddition::None), (2, CycleAddition::None), (6, CycleAddition::None), (3, CycleAddition::None), (3, CycleAddition::None), (3, CycleAddition::None), (3, CycleAddition::None), (2, CycleAddition::None), (2, CycleAddition::None), (2, CycleAddition::None), (2, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), 
34    (2, CycleAddition::BranchOnPage), (6, CycleAddition::None), (0, CycleAddition::None), (6, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), (2, CycleAddition::None), (5, CycleAddition::None), (2, CycleAddition::None), (5, CycleAddition::None), (5, CycleAddition::None), (5, CycleAddition::None), (5, CycleAddition::None), (5, CycleAddition::None), 
35    (2, CycleAddition::None), (6, CycleAddition::None), (2, CycleAddition::None), (6, CycleAddition::None), (3, CycleAddition::None), (3, CycleAddition::None), (3, CycleAddition::None), (3, CycleAddition::None), (2, CycleAddition::None), (2, CycleAddition::None), (2, CycleAddition::None), (2, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), 
36    (2, CycleAddition::BranchOnPage), (5, CycleAddition::PageBoundaryCrossed), (0, CycleAddition::None), (5, CycleAddition::PageBoundaryCrossed), (4, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), (2, CycleAddition::None), (4, CycleAddition::PageBoundaryCrossed), (2, CycleAddition::None), (4, CycleAddition::PageBoundaryCrossed), (4, CycleAddition::PageBoundaryCrossed), (4, CycleAddition::PageBoundaryCrossed), (4, CycleAddition::PageBoundaryCrossed), (4, CycleAddition::PageBoundaryCrossed), 
37    (2, CycleAddition::None), (6, CycleAddition::None), (2, CycleAddition::None), (8, CycleAddition::None), (3, CycleAddition::None), (3, CycleAddition::None), (5, CycleAddition::None), (5, CycleAddition::None), (2, CycleAddition::None), (2, CycleAddition::None), (2, CycleAddition::None), (2, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), (6, CycleAddition::None), (6, CycleAddition::None), 
38    (2, CycleAddition::BranchOnPage), (5, CycleAddition::PageBoundaryCrossed), (0, CycleAddition::None), (8, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), (6, CycleAddition::None), (6, CycleAddition::None), (2, CycleAddition::None), (4, CycleAddition::PageBoundaryCrossed), (2, CycleAddition::None), (7, CycleAddition::None), (4, CycleAddition::PageBoundaryCrossed), (4, CycleAddition::PageBoundaryCrossed), (7, CycleAddition::None), (7, CycleAddition::None), 
39    (2, CycleAddition::None), (6, CycleAddition::None), (2, CycleAddition::None), (8, CycleAddition::None), (3, CycleAddition::None), (3, CycleAddition::None), (5, CycleAddition::None), (5, CycleAddition::None), (2, CycleAddition::None), (2, CycleAddition::None), (2, CycleAddition::None), (2, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), (6, CycleAddition::None), (6, CycleAddition::None), 
40    (2, CycleAddition::BranchOnPage), (5, CycleAddition::PageBoundaryCrossed), (0, CycleAddition::None), (8, CycleAddition::None), (4, CycleAddition::None), (4, CycleAddition::None), (6, CycleAddition::None), (6, CycleAddition::None), (2, CycleAddition::None), (4, CycleAddition::PageBoundaryCrossed), (2, CycleAddition::None), (7, CycleAddition::None), (4, CycleAddition::PageBoundaryCrossed), (4, CycleAddition::PageBoundaryCrossed), (7, CycleAddition::None), (7, CycleAddition::None)
41];
42
43#[derive(Debug, Clone, Copy)]
44enum CycleAddition {
45    None,
46    PageBoundaryCrossed,
47    BranchOnPage
48}
49
50#[derive(Debug, Clone, Copy)]
51enum Instruction {
52    /// add with carry
53    ADC,
54    /// and (with accumulator)
55    AND,
56    /// arithmetic shift left
57    ASL,
58    /// branch on carry clear
59    BCC,
60    /// branch on carry set
61    BCS,
62    /// branch on equal (zero set)
63    BEQ,
64    /// bit test
65    BIT,
66    /// branch on minus (negative set)
67    BMI,
68    /// branch on not equal (zero clear)
69    BNE,
70    /// branch on plus (negative clear)
71    BPL,
72    /// break/interrupt
73    BRK,
74    /// branch on overflow clear
75    BVC,
76    /// branch on overflow set
77    BVS,
78    /// clear carry
79    CLC,
80    /// clear decimal
81    CLD,
82    /// clear interrupt disable
83    CLI,
84    /// clear overflow
85    CLV,
86    /// compare (with accumulator)
87    CMP,
88    /// compare with X
89    CPX,
90    /// compare with Y
91    CPY,
92    /// decrement
93    DEC,
94    /// decrement X
95    DEX,
96    /// decrement Y
97    DEY,
98    /// exclusive or (with accumulator)
99    EOR,
100    /// increment
101    INC,
102    /// increment X
103    INX,
104    /// increment Y
105    INY,
106    /// jump
107    JMP,
108    /// jump subroutine
109    JSR,
110    /// load accumulator
111    LDA,
112    /// load x
113    LDX,
114    /// load y
115    LDY,
116    /// logical shift right
117    LSR,
118    /// no operation
119    NOP,
120    /// or with accumulator
121    ORA,
122    /// push accumulator
123    PHA,
124    /// push processor status (SR)
125    PHP,
126    /// pull accumulator
127    PLA,
128    /// pull processor status (SR)
129    PLP,
130    /// rotate left
131    ROL,
132    /// rotate right
133    ROR,
134    /// return from subroutine
135    RTS,
136    /// return from interrupt
137    RTI,
138    /// subtract with carry
139    SBC,
140    /// set carry
141    SEC,
142    /// set decimal
143    SED,
144    /// set interrupt disable
145    SEI,
146    /// store accumulator
147    STA,
148    /// store x
149    STX,
150    /// store y
151    STY,
152    /// transfer accumulator to X
153    TAX,
154    /// transfer accumulator to Y
155    TAY,
156    /// transfer stack pointer to X
157    TSX,
158    /// transfer X to accumulator
159    TXA,
160    /// transfer X to stack pointer
161    TXS,
162    /// transfer Y to accumulator
163    TYA,
164    
165    // VVVV Illegal
166
167    /// AND oper + LSR
168    ALR,
169    /// AND oper + set C asl 7
170    ANC,
171    /// AND X + AND oper
172    ANE,
173    /// AND oper + ROR
174    ARR,
175    /// DEC oper + CMP oper
176    DCP,
177    /// INC oper + SBC oper
178    ISC,
179    /// LDA/TSX oper
180    LAS,
181    /// LDA oper + LDX oper
182    LAX,
183    /// Store * AND oper in A and X
184    LXA,
185    /// ROL oper + AND oper
186    RLA,
187    /// ROR oper + ADC oper
188    RRA,
189    /// A AND X -> M (what the fuck)
190    SAX,
191    /// (A AND X) - oper -> X
192    SBX,
193    /// A AND X AND (H+1) -> M (what the fuck)
194    SHA,
195    /// X AND (H+1) -> M
196    SHX,
197    /// Y AND (H+1) -> M
198    SHY,
199    /// ASL oper + ORA oper
200    SLO,
201    /// LSR oper + EOR oper
202    SRE,
203    /// A AND X -> SP, A AND X AND (H+1) -> M
204    TAS,
205    /// SBC oper + NOP (what the fuck)
206    USBC,
207    /// Jams.
208    JAM,
209}
210
211#[derive(Debug, Copy, Clone)]
212enum AddressMode {
213    Accumulator,
214    Absolute,
215    AbsoluteXIndex,
216    AbsoluteYIndex,
217    Immediate,
218    Implied,
219    Indirect,
220    IndirectXIndex,
221    IndirectYIndex,
222    Relative,
223    Zeropage,
224    ZeropageXIndex,
225    ZeropageYIndex,
226}
227
228/// Representation of 6502's status register. You may want to construct this and pass it in when constructing a CPU.
229/// Using [StatusRegister]'s default() will return a status register with all fields set to false (0).
230#[derive(Debug, Default, Clone, Copy)]
231pub struct StatusRegister {
232    pub negative: bool,
233    pub overflow: bool,
234    pub ignored: bool,
235    pub _break: bool,
236    pub decimal: bool,
237    pub interrupt: bool,
238    pub zero: bool,
239    pub carry: bool
240}
241
242impl StatusRegister {
243
244    /// Utility for converting a StatusRegister to a u8. Helpful for debugging and testing.
245    pub fn to_u8(&self) -> u8 {
246        (self.negative as u8) << 7 |
247        (self.overflow as u8) << 6 |
248        (self.ignored as u8) << 5 |
249        (self._break as u8) << 4 |
250        (self.decimal as u8) << 3 |
251        (self.interrupt as u8) << 2 |
252        (self.zero as u8) << 1 |
253        (self.carry as u8)
254    }
255
256    /// Utility for converting a u8 to a StatusRegister. Helpful for debugging and testing.
257    pub fn from_u8(x: u8) -> Self {
258       StatusRegister {
259           negative: (x & 0b10000000) >> 7 == 1,
260           overflow: (x & 0b01000000) >> 6 == 1,
261           ignored: (x & 0b00100000) >> 5 == 1,
262           _break: (x & 0b00010000) >> 4== 1,
263           decimal: (x & 0b00001000) >> 3 == 1,
264           interrupt: (x & 0b00000100) >> 2 == 1,
265           zero: (x & 0b00000010) >> 1 == 1,
266           carry: (x & 0b00000001) == 1
267       }
268    }
269}
270
271#[cfg(test)]
272mod status_register_test {
273    use super::StatusRegister;
274
275    #[test]
276    pub fn test() {
277        let status = StatusRegister::from_u8(106);
278        assert_eq!(status.to_u8(), 106);
279    }
280}
281
282/// Determines how the CPU should handle JAM instructions.
283#[derive(Debug, Clone, Copy)]
284pub enum JamBehavior {
285    /// Will set the CPU into a "jammed" state where calling step() will not execute instructions until reset() is called. 
286    Jam,
287    /// Treat JAM instructions as NOP instructions. In this case, the cycles of a JAM instruction will always be zero.
288    Nop,
289    /// Call panic!() on a JAM instruction.
290    Panic
291}
292
293/// Determines how the CPU should handle illegal instructions.
294#[derive(Debug, Clone, Copy)]
295pub enum IllegalBehavior {
296    /// Treat illegal instructions as legal instructions and execute them.
297    Execute,
298    /// Treat illegal instructions as NOP instructions. In this case, the cycles of illegal instructions will always be zero.
299    Nop,
300    /// Call panic!() on an illegal instruction.
301    Panic
302}
303
304/// Used to customize behavior for the Cpu.
305#[derive(Debug, Clone, Copy)]
306pub struct CpuConfig {
307    /// If true, ADC and SBC will carry out BCD arithmetic when the decimal flag is set. If false,
308    /// ADC and SBC will carry out normal arithmetic regardless of what the decimal flag is.
309    pub bcd_support: bool,
310    /// How the CPU should handle a JAM instruction.
311    pub jam_behavior: JamBehavior,
312    /// How the CPU should handle illegal instructions.
313    pub illegal_behavior: IllegalBehavior 
314}
315
316/// By default, CpuConfig will have decimal support enabled, JAM instructions will be treated as NOPs, and illegal instructions will be executed.
317impl Default for CpuConfig {
318    fn default() -> Self {
319        CpuConfig { 
320            bcd_support: true,
321            jam_behavior: JamBehavior::Jam,
322            illegal_behavior: IllegalBehavior::Execute 
323        }
324    }
325}
326
327impl CpuConfig {
328    pub fn bcd_support(mut self, x: bool) -> Self {
329        self.bcd_support = x;
330        self
331    }
332
333    pub fn jam_behavior(mut self, x: JamBehavior) -> Self {
334        self.jam_behavior = x;
335        self
336    }
337
338    pub fn illegal_behavior(mut self, x: IllegalBehavior) -> Self {
339        self.illegal_behavior = x;
340        self
341    }
342}
343
344/// The return value of the Cpu's step().
345pub enum CpuStepReturn {
346    /// What the Cpu's step() returns on a successful fetch-decode-execute cycle.
347    Ok(usize),
348    /// What the Cpu returns when it is in a "jammed" state, i.e when a JAM instruction was just
349    /// executed or after a JAM instruction has been executed but a reset has not yet occurred.
350    /// In this case the CPU has not done any fetch-decod-execute cycle.
351    Jam 
352}
353
354/// For executing 6502 instructions.
355pub struct Cpu<T: bus::CPUMemory> {
356    pub previous_program_counter: u16,
357    pub program_counter: u16,
358    pub accumulator: u8,
359    pub x: u8,
360    pub y: u8,
361    pub status: StatusRegister,
362    pub stack_pointer: u8,
363    pub bus: T,
364    pub config: CpuConfig,
365    pub jammed: bool
366}
367
368impl<T: bus::CPUMemory> Display for Cpu<T> {
369    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
370        write!(f, "{:5}| {:6} | {:18} | {:6}\n", "REG", "HEX", "BIN", "DEC")?;
371        write!(f, "{:-<43}\n", "")?;
372        write!(f, "{:5}| {:#6X} | {:#18b} | {:6}\n", "PC", self.program_counter, self.program_counter, self.program_counter)?;
373        write!(f, "{:5}| {:#6X} | {:#18b} | {:6}\n", "ACC", self.accumulator, self.accumulator, self.accumulator)?;
374        write!(f, "{:5}| {:#6X} | {:#18b} | {:6}\n", "X", self.x, self.x, self.x)?;
375        write!(f, "{:5}| {:#6X} | {:#18b} | {:6}\n", "Y", self.y, self.y, self.y)?;
376        write!(f, "{:5}| {:#6X} | {:#18b} | {:6}\n", "STAT", self.status.to_u8(), self.status.to_u8(), self.status.to_u8())?;
377        write!(f, "{:5}| {:#6X} | {:#18b} | {:6}\n", "SP", self.stack_pointer, self.stack_pointer, self.stack_pointer) 
378    }
379}
380
381impl<T: bus::CPUMemory> Cpu<T> {
382    /// Construct a new Cpu given a config and a status register to start with.
383    pub fn new(bus: T, config: CpuConfig, status: StatusRegister) -> Self {
384        Cpu {
385            previous_program_counter: 0x0,
386            program_counter: 0x400,
387            accumulator: 0,
388            x: 0,
389            y: 0,
390            status,
391            stack_pointer: 0xFD,
392            bus,
393            config,
394            jammed: false
395        }
396    }
397
398    fn set_if_zero(&mut self, operand: u8) {
399        if operand == 0 {
400            self.status.zero = true;
401        } else {
402            self.status.zero = false;
403        }
404    }
405
406    fn set_if_negative(&mut self, operand: u8) {
407        self.status.negative = (operand as i8) < 0;
408    }
409
410    /// (Operand, Address, PageBoundaryCrossed)
411    /// PageBoundaryCrossed will only possibly be true in AbsoluteXIndex, AbsoluteYIndex, and IndirectYIndex
412    fn fetch_operand(&mut self, address_mode: AddressMode) -> (u8, u16, bool) {
413        match address_mode {
414            AddressMode::Accumulator => {
415                (self.accumulator, 0, false)
416            },
417            AddressMode::Absolute => {
418                let low_byte = self.bus.read(self.program_counter.wrapping_add(1));
419                let high_byte = self.bus.read(self.program_counter.wrapping_add(2));
420                self.program_counter = self.program_counter.wrapping_add(2);
421                let address = ((high_byte as u16) << 8) | low_byte as u16;
422                (self.bus.read(address), address, false)
423            },
424            AddressMode::AbsoluteXIndex => {
425                let low_byte = self.bus.read(self.program_counter.wrapping_add(1));
426                let high_byte = self.bus.read(self.program_counter.wrapping_add(2));
427                self.program_counter = self.program_counter.wrapping_add(2);
428                let address = ((high_byte as u16) << 8) | low_byte as u16;
429                let address_indexed = address.wrapping_add(self.x as u16);
430                (self.bus.read(address_indexed), address_indexed, address_indexed & 0xFF00 != address & 0xFF00)
431            },
432            AddressMode::AbsoluteYIndex => {
433                let low_byte = self.bus.read(self.program_counter.wrapping_add(1));
434                let high_byte = self.bus.read(self.program_counter.wrapping_add(2));
435                self.program_counter = self.program_counter.wrapping_add(2);
436                let address = ((high_byte as u16) << 8) | low_byte as u16;
437                let address_indexed = address.wrapping_add(self.y as u16);
438                (self.bus.read(address_indexed), address_indexed, address_indexed & 0xFF00 != address & 0xFF00)
439            },
440            AddressMode::Immediate => {
441                let byte = self.bus.read(self.program_counter.wrapping_add(1));
442                self.program_counter = self.program_counter.wrapping_add(1);
443                (byte, self.program_counter, false)
444            },
445            AddressMode::Implied => {
446                (0, 0, false)
447            },
448            AddressMode::Indirect => {
449                let low_byte = self.bus.read(self.program_counter + 1);
450                let high_byte = self.bus.read(self.program_counter + 2);
451                self.program_counter = self.program_counter.wrapping_add(2);
452                let address = (u16::from(high_byte) << 8) | u16::from(low_byte);
453                // page boundary bug
454                if address & 0xFF == 0xFF {
455                    let low_byte = self.bus.read(address);
456                    let high_byte = self.bus.read(address & 0xFF00);
457                    let indirect = (u16::from(high_byte) << 8) | u16::from(low_byte);
458                    (0,indirect, false)
459                } else {
460                    let low_byte = self.bus.read(address);
461                    let high_byte = self.bus.read(address.wrapping_add(1));
462                    let indirect = (u16::from(high_byte) << 8) | u16::from(low_byte);
463                    (0,indirect, false)
464                }
465                
466            },
467            AddressMode::IndirectXIndex => {
468                let byte = self.bus.read(self.program_counter.wrapping_add(1));
469                self.program_counter = self.program_counter.wrapping_add(1);
470                let low_byte = self.bus.read((byte.wrapping_add(self.x)) as u16);
471                let high_byte = self.bus.read(byte.wrapping_add(self.x).wrapping_add(1) as u16);
472                let address = ((high_byte as u16) << 8) | low_byte as u16;
473
474                (self.bus.read(address), address, false)
475            },
476            AddressMode::IndirectYIndex => {
477                // fetch  address at zero page
478                let zeropage_byte = self.bus.read(self.program_counter.wrapping_add(1));
479                self.program_counter = self.program_counter.wrapping_add(1);
480                let low_byte = self.bus.read((zeropage_byte) as u16);
481                let high_byte = self.bus.read((zeropage_byte.wrapping_add(1)) as u16);
482                let address = ((high_byte as u16) << 8) | low_byte as u16;
483                let address_indexed = address.wrapping_add(self.y as u16);
484                (self.bus.read(address_indexed), address_indexed, address_indexed & 0xFF00 != address & 0xFF00)
485            },
486            AddressMode::Relative => {
487                // this will be broken
488                let byte = self.bus.read(self.program_counter.wrapping_add(1));
489                let byte = byte as i8;
490                self.program_counter = self.program_counter.wrapping_add(1);
491                let address = (self.program_counter as i16).wrapping_add(byte as i16);
492                (0,address as u16, false)
493            },
494            AddressMode::Zeropage => {
495                let low_byte = self.bus.read(self.program_counter.wrapping_add(1));
496                self.program_counter = self.program_counter.wrapping_add(1);
497                (self.bus.read(low_byte as u16), low_byte as u16, false)
498            },
499            AddressMode::ZeropageXIndex => {
500                let low_byte = self.bus.read(self.program_counter.wrapping_add(1));
501                self.program_counter = self.program_counter.wrapping_add(1);
502                (self.bus.read(self.x.wrapping_add(low_byte) as u16), self.x.wrapping_add(low_byte) as u16, false)
503            },
504            AddressMode::ZeropageYIndex => {
505                let low_byte = self.bus.read(self.program_counter.wrapping_add(1));
506                self.program_counter = self.program_counter.wrapping_add(1);
507                (self.bus.read(self.y.wrapping_add(low_byte) as u16), self.y.wrapping_add(low_byte) as u16, false)
508            }
509        }
510
511    }
512
513    /// Used to emulate a reset, setting the program counter based off the bytes at 0xFFFC and 0xFFFD.
514    pub fn reset(&mut self) {
515        let high_byte = self.bus.read(0xFFFD);
516        let low_byte = self.bus.read(0xFFFC);
517
518        let new_address = (high_byte as u16) << 8 & (low_byte as u16);
519        self.program_counter = new_address;
520    }
521
522    /// step() will run the fetch, decode, and execute cycle for one instruction, and return the number of cycles (it would take on a real 6502)
523    /// to do so.
524    pub fn step(&mut self) -> CpuStepReturn {
525        let opcode = self.bus.read(self.program_counter);
526
527        let high_nibble = (opcode & 0xF0) >> 4;
528        let low_nibble = opcode & 0x0F;
529
530        let (opcode, address_mode) = LOOKUP_TABLE[(high_nibble * 16 + low_nibble) as usize];
531        let (operand, address, page_boundary_crossed) = self.fetch_operand(address_mode);
532
533        match opcode {
534            Instruction::ADC => self.adc(operand),
535            Instruction::AND => self.and(operand),
536            Instruction::ASL => match address_mode {
537                AddressMode::Accumulator => self.asl(address, operand, true),
538                _ => self.asl(address, operand, false)
539            },
540            Instruction::BCC => self.bcc(address),
541            Instruction::BCS => self.bcs(address),
542            Instruction::BEQ => self.beq(address),
543            Instruction::BIT => self.bit(operand),
544            Instruction::BMI => self.bmi(address),
545            Instruction::BNE => self.bne(address),
546            Instruction::BPL => self.bpl(address),
547            Instruction::BRK => self.brk(),
548            Instruction::BVC => self.bvc(address),
549            Instruction::BVS => self.bvs(address),
550            Instruction::CLC => self.clc(),
551            Instruction::CLD => self.cld(),
552            Instruction::CLI => self.cli(),
553            Instruction::CLV => self.clv(),
554            Instruction::CMP => self.cmp(operand),
555            Instruction::CPX => self.cpx(operand),
556            Instruction::CPY => self.cpy(operand),
557            Instruction::DEC => self.dec(address, operand),
558            Instruction::DEX => self.dex(),
559            Instruction::DEY => self.dey(),
560            Instruction::EOR => self.eor(operand),
561            Instruction::INC => self.inc(address, operand),
562            Instruction::INX => self.inx(),
563            Instruction::INY => self.iny(),
564            Instruction::JMP => self.jmp(address),
565            Instruction::JSR => self.jsr(address),
566            Instruction::LDA => self.lda(operand),
567            Instruction::LDX => self.ldx(operand),
568            Instruction::LDY => self.ldy(operand),
569            Instruction::LSR => match address_mode {
570                AddressMode::Accumulator => self.lsr(address, operand, true),
571                _ => self.lsr(address, operand, false)
572            },
573            Instruction::NOP => self.nop(),
574            Instruction::ORA => self.ora(operand),
575            Instruction::PHA => self.pha(),
576            Instruction::PHP => self.php(),
577            Instruction::PLA => self.pla(),
578            Instruction::PLP => self.plp(),
579            Instruction::ROL => match address_mode {
580                AddressMode::Accumulator => self.rol(address, operand, true),
581                _ => self.rol(address, operand, false)
582            },
583            Instruction::ROR => match address_mode {
584                AddressMode::Accumulator => self.ror(address, operand, true),
585                _ => self.ror(address, operand, false)
586            },
587            Instruction::RTS => self.rts(),
588            Instruction::RTI => self.rti(),
589            Instruction::SBC => self.sbc(operand),
590            Instruction::SEC => self.sec(),
591            Instruction::SED => self.sed(),
592            Instruction::SEI => self.sei(),
593            Instruction::STA => self.sta(address),
594            Instruction::STX => self.stx(address),
595            Instruction::STY => self.sty(address),
596            Instruction::TAX => self.tax(),
597            Instruction::TAY => self.tay(),
598            Instruction::TSX => self.tsx(),
599            Instruction::TXA => self.txa(),
600            Instruction::TXS => self.txs(),
601            Instruction::TYA => self.tya(),
602            // VVVV Jam
603            Instruction::JAM => {
604                match self.config.jam_behavior {
605                    JamBehavior::Jam => {
606                        self.jammed = true;
607                        return CpuStepReturn::Jam;
608                    },
609                    JamBehavior::Nop => {
610                        self.nop();
611                        return CpuStepReturn::Ok(0);
612                    },
613                    JamBehavior::Panic => {
614                        panic!("A JAM instruction was encountered and this Cpu's JamBehavior has been set to Panic.")
615                    }
616                }
617            },
618            // VVVV Illegal
619            _ => {
620                match self.config.illegal_behavior {
621                    IllegalBehavior::Execute => match opcode {
622                        Instruction::ALR => self.alr(operand),
623                        Instruction::ANC => self.anc(operand),
624                        Instruction::ANE => self.ane(operand),
625                        Instruction::ARR => self.arr(address, operand),
626                        Instruction::DCP => self.dcp(address, operand),
627                        Instruction::ISC => self.isc(address, operand),
628                        Instruction::LAS => self.las(operand),
629                        Instruction::LAX => self.lax(operand),
630                        Instruction::LXA => self.lxa(operand),
631                        Instruction::RLA => self.rla(address, operand),
632                        Instruction::RRA => self.rra(address, operand),
633                        Instruction::SAX => self.sax(address),
634                        Instruction::SBX => self.sbx(operand),
635                        Instruction::SHA => self.sha(address),
636                        Instruction::SHX => self.shx(address),
637                        Instruction::SHY => self.shy(address),
638                        Instruction::SLO => self.slo(address, operand),
639                        Instruction::SRE => self.sre(address, operand),
640                        Instruction::TAS => self.tas(address),
641                        Instruction::USBC => self.usbc(operand),
642                        // all other instructions were checked in outer match
643                        _ => unreachable!()
644                    },
645                    IllegalBehavior::Nop => {
646                        self.nop();
647                        return CpuStepReturn::Ok(0)
648                    },
649                    IllegalBehavior::Panic => {
650                        panic!("An illegal instruction was encountered and this Cpu's IllegalBehavior has been set to Panic.")
651                    },
652                }
653            }
654        }
655
656        self.previous_program_counter = self.program_counter;
657        self.program_counter = self.program_counter.wrapping_add(1);
658
659        let (cycles, addition) = CYCLE_TIMES[(high_nibble * 16 + low_nibble) as usize];
660        match addition {
661            CycleAddition::None => CpuStepReturn::Ok(cycles as usize),
662            CycleAddition::PageBoundaryCrossed => {
663                if page_boundary_crossed {
664                    CpuStepReturn::Ok(cycles as usize + 1)
665                } else {
666                    CpuStepReturn::Ok(cycles as usize + 1)
667                }
668            },
669            CycleAddition::BranchOnPage => {
670                if self.previous_program_counter & 0xFF00 == self.program_counter & 0xFF00 {
671                    CpuStepReturn::Ok(cycles as usize + 1)
672                } else {
673                    CpuStepReturn::Ok(cycles as usize + 2)
674                }
675            },
676        }
677
678    }
679
680    fn push_to_stack(&mut self, x: u8) {
681        self.bus.write(self.stack_pointer as u16 + 0x100, x);
682        self.stack_pointer = self.stack_pointer.wrapping_sub(1);
683    }
684
685    fn pop_from_stack(&mut self) -> u8 {
686        self.stack_pointer = self.stack_pointer.wrapping_add(1);
687        let x = self.bus.read(self.stack_pointer as u16 + 0x100);
688        x
689    }
690
691    fn compare(&mut self, r: i8, val: i8) {
692        if r as u8 >= val as u8 {
693            self.status.carry = true;
694        } else {
695            self.status.carry = false;
696        }
697
698        if r as i8 == val as i8 {
699            self.status.zero = true;
700        } else {
701            self.status.zero = false;
702        }
703
704        let diff: i8 = r.wrapping_sub(val as i8);
705        if diff < 0 {
706            self.status.negative = true;
707        } else {
708            self.status.negative = false;
709        }
710    }
711
712    fn lower_digit(&mut self, x: u8) -> u8 {
713        x | 0xF
714    }
715
716    fn upper_digit(&mut self, x: u8) -> u8 {
717        (x | 0xF0) >> 4
718    }
719
720    // Transfer instructions
721    fn lda(&mut self, operand: u8) {
722        self.accumulator = operand;
723        self.set_if_negative(operand);
724        self.set_if_zero(operand);
725    }
726
727    fn ldx(&mut self, operand: u8) {
728        self.x = operand;
729        self.set_if_negative(operand);
730        self.set_if_zero(operand);
731    }
732
733    fn ldy(&mut self, operand: u8) {
734        self.y = operand;
735        self.set_if_negative(operand);
736        self.set_if_zero(operand);
737    }
738
739    fn sta(&mut self, address: u16) {
740        self.bus.write(address, self.accumulator);
741    }
742
743    fn stx(&mut self, address: u16) {
744        self.bus.write(address, self.x);
745    }
746
747    fn sty(&mut self, address: u16) {
748        self.bus.write(address, self.y);
749    }
750
751    fn tax(&mut self) {
752        self.x = self.accumulator;
753        self.set_if_negative(self.x);
754        self.set_if_zero(self.x);
755    }
756
757    fn tay(&mut self) {
758        self.y = self.accumulator;
759        self.set_if_negative(self.y);
760        self.set_if_zero(self.y);
761    }
762
763    fn tsx(&mut self) {
764        self.x = self.stack_pointer;
765        self.set_if_negative(self.x);
766        self.set_if_zero(self.x);
767    }
768
769    fn txa(&mut self) {
770        self.accumulator = self.x;
771        self.set_if_negative(self.accumulator);
772        self.set_if_zero(self.accumulator);
773   }
774
775    fn txs(&mut self) {
776        self.stack_pointer = self.x;
777    }
778
779    fn tya(&mut self) {
780        self.accumulator = self.y;
781        self.set_if_negative(self.accumulator);
782        self.set_if_zero(self.accumulator);
783   }
784
785    // Stack instructions
786    fn pha(&mut self) {
787        self.push_to_stack(self.accumulator);
788    }
789
790    fn php(&mut self) {
791        self.push_to_stack(self.status.to_u8() | (0b00110000));
792    }
793
794    fn pla(&mut self) {
795        self.stack_pointer = self.stack_pointer.wrapping_add(1);
796        let new_accumulator = self.bus.read(self.stack_pointer as u16 + 0x100);
797        self.accumulator = new_accumulator;
798        self.set_if_negative(new_accumulator);
799        self.set_if_zero(new_accumulator);
800    }
801
802
803    fn plp(&mut self) {
804        let stack_status = self.pop_from_stack();
805        let current_status = self.status.to_u8();
806        
807        let new_status = (stack_status & 0b11001111) | (current_status & 0b00110000);
808        self.status = StatusRegister::from_u8(new_status);
809    }
810
811    // Decrements & increments
812    fn dec(&mut self, address: u16, operand: u8) {
813        self.bus.write(address, operand.wrapping_sub(1));
814        self.set_if_negative(operand.wrapping_sub(1));
815        self.set_if_zero(operand.wrapping_sub(1));
816    }
817
818    fn dex(&mut self) {
819        self.x = self.x.wrapping_sub(1);
820        self.set_if_negative(self.x);
821        self.set_if_zero(self.x);
822    }
823
824    fn dey(&mut self) {
825        self.y = self.y.wrapping_sub(1);
826        self.set_if_negative(self.y);
827        self.set_if_zero(self.y);
828    }
829
830    fn inc(&mut self, address: u16, operand: u8) {
831        self.bus.write(address, operand.wrapping_add(1));
832        self.set_if_negative(operand.wrapping_add(1));
833        self.set_if_zero(operand.wrapping_add(1));
834    }
835
836    fn inx(&mut self) {
837        self.x = self.x.wrapping_add(1);
838        self.set_if_negative(self.x);
839        self.set_if_zero(self.x);
840    }
841
842    fn iny(&mut self) {
843        self.y = self.y.wrapping_add(1);
844        self.set_if_negative(self.y);
845        self.set_if_zero(self.y);
846    }
847
848    // Arithmetic operations
849    fn adc(&mut self, operand: u8) {
850        let mut result: u16 = u16::from(self.accumulator) + u16::from(operand) + u16::from(self.status.carry);
851        if self.status.decimal && self.config.bcd_support {
852            let mut sum = (self.accumulator & 0xF) + (operand & 0xF) + u8::from(self.status.carry);
853            if sum >= 0xA {
854                sum = ((sum + 0x6) & 0xF) + 0x10;
855            }
856            let mut sum = u16::from(self.accumulator & 0xF0) + u16::from(operand & 0xF0) + u16::from(sum);
857            self.status.zero = result & 0xFF == 0;
858            self.status.negative = (sum & 0x80) > 0;
859            self.status.overflow = (!(self.accumulator ^ operand) & (self.accumulator ^ sum as u8) & 0x80) > 0;
860            if sum >= 0xA0 {
861                sum += 0x60;
862            }
863            self.status.carry = sum >= 0x100;
864            result = sum & 0xFF;
865        } else {
866            self.status.carry = result > u16::from(u8::max_value());
867            self.status.zero = result as u8 == 0;
868            self.status.overflow = (!(self.accumulator ^ operand) & (self.accumulator ^ result as u8) & 0x80) > 0;
869            self.status.negative = (result as u8 & 0x80) > 0;
870        }
871        self.accumulator = result as u8;
872    }
873
874    fn sbc(&mut self, operand: u8) {
875        let mut result = u16::from(self.accumulator) + u16::from(!operand) + (if self.status.carry { 1 } else { 0 });
876        self.status.carry = result > u16::from(u8::max_value());
877        self.status.zero = result as u8 == 0;
878        self.status.overflow = ((self.accumulator ^ operand) & (self.accumulator ^ result as u8) & 0x80) > 0;
879        self.status.negative = (result as u8 & 0x80) > 0;
880        if self.status.decimal && self.status.decimal {
881            let operand = operand as i16;
882            let mut sum = (self.accumulator & 0xF) as i16 - (operand & 0xF) + self.status.carry as i16 - 1;
883            if sum < 0 {
884                sum = ((sum - 0x6) & 0xF) - 0x10;
885            }
886            let mut sum = (self.accumulator & 0xF0) as i16 - (operand & 0xF0) + sum;
887            if sum < 0 {
888                sum -= 0x60;
889            }
890            result = (sum & 0xFF) as u16;
891        }
892        self.accumulator = result as u8;
893    }
894
895    // Logical operations
896    fn and(&mut self, operand: u8) {
897        self.accumulator &= operand;
898        self.set_if_negative(self.accumulator);
899        self.set_if_zero(self.accumulator);
900    }
901
902    fn ora(&mut self, operand: u8) {
903        self.accumulator |= operand;
904        self.set_if_negative(self.accumulator);
905        self.set_if_zero(self.accumulator);
906    }
907
908    fn eor(&mut self, operand: u8) {
909        self.accumulator ^= operand;
910        self.set_if_negative(self.accumulator);
911        self.set_if_zero(self.accumulator);
912    }
913
914    // Shift & rotate instructions
915    fn asl(&mut self, address: u16, operand: u8, accumulator: bool) {
916        if accumulator {
917            self.status.carry = self.accumulator >> 7 == 1;
918            self.accumulator = self.accumulator << 1;
919            self.status.negative = self.accumulator & 0x80 > 0;
920            self.status.zero = self.accumulator == 0;
921        } else {
922            self.status.carry = operand >> 7 == 1;
923            let new_num = operand << 1;
924            self.bus.write(address, new_num);
925            self.status.negative = new_num & 0x80 > 0;
926            self.status.zero = new_num == 0;
927        }
928    }
929
930    fn lsr(&mut self, address: u16, operand: u8, accumulator: bool) {
931        if accumulator {
932            self.status.carry = self.accumulator & 0b1 == 1;
933            self.accumulator = self.accumulator >> 1;
934            self.set_if_negative(self.accumulator);
935            self.set_if_zero(self.accumulator);
936        } else {
937            self.status.carry = operand & 0b1 == 1;
938            let new_num = operand >> 1;
939            self.bus.write(address, new_num);
940            self.set_if_negative(new_num);
941            self.set_if_zero(new_num);
942        }
943    }
944
945    fn rol(&mut self, address: u16, operand: u8, accumulator: bool) {
946        if accumulator {
947            let carry = self.status.carry;
948            self.status.carry = (self.accumulator >> 7) == 1;
949            self.accumulator = (self.accumulator << 1) + carry as u8;
950            self.status.negative = self.accumulator & 0x80 > 0;
951            self.status.zero = self.accumulator == 0;
952        } else {
953            let carry = self.status.carry;
954            self.status.carry = (operand >> 7) == 1;
955            let new = (operand << 1) + carry as u8;
956            self.bus.write(address, new);
957            self.status.negative = new & 0x80 > 0;
958            self.status.zero = new == 0;
959        }
960    }
961
962    fn ror(&mut self, address: u16, operand: u8, accumulator: bool) {
963        if accumulator {
964            let carry = self.status.carry as u8;
965            self.status.carry = (self.accumulator & 1) == 1;
966            self.accumulator = (self.accumulator >> 1) + (carry << 7);
967            self.status.negative = self.accumulator & 0x80 > 0;
968            self.status.zero = self.accumulator == 0;
969        } else {
970            let carry = self.status.carry as u8;
971            self.status.carry = (operand & 1) == 1;
972            let new = (operand >> 1) + (carry << 7);
973            self.bus.write(address, new);
974            self.status.negative = new & 0x80 > 0;
975            self.status.zero = new == 0;
976        }
977    }
978
979    // Flag instructions
980    fn clc(&mut self) {
981        self.status.carry = false;
982    }
983
984    fn cld(&mut self) {
985        self.status.decimal = false;
986    }
987
988    fn cli(&mut self) {
989        self.status.interrupt = false;
990    }
991
992    fn clv(&mut self) {
993        self.status.overflow = false;
994    }
995
996    fn sec(&mut self) {
997        self.status.carry = true;
998    }
999
1000    fn sed(&mut self) {
1001        self.status.decimal = true;
1002    }
1003
1004    fn sei(&mut self) {
1005       self.status.interrupt = true;
1006    }
1007
1008    // Comparisons - stolen from another rust emulator
1009    fn cmp(&mut self, operand: u8) {
1010        self.compare(self.accumulator as i8, operand as i8);
1011    }
1012
1013    fn cpx(&mut self, operand: u8) {
1014        self.compare(self.x as i8, operand as i8);
1015    }
1016
1017    fn cpy(&mut self, operand: u8) {
1018        self.compare(self.y as i8, operand as i8);
1019    }
1020
1021    // Branch instructions
1022    fn bcc(&mut self, address: u16) {
1023        if !self.status.carry {
1024            self.program_counter = address;
1025        }
1026    }
1027
1028    fn bcs(&mut self, address: u16) {
1029        if self.status.carry {
1030            self.program_counter = address;
1031        }
1032    }
1033
1034    fn beq(&mut self, address: u16) {
1035        if self.status.zero {
1036            self.program_counter = address;
1037        }
1038    }
1039
1040    fn bmi(&mut self, address: u16) {
1041        if self.status.negative {
1042            self.program_counter = address;
1043        }
1044    }
1045
1046    fn bne(&mut self, address: u16) {
1047        if !self.status.zero {
1048            self.program_counter = address;
1049        }
1050    }
1051
1052    fn bpl(&mut self, address: u16) {
1053        if !self.status.negative {
1054            self.program_counter = address;
1055        }
1056    }
1057
1058    fn bvc(&mut self, address: u16) {
1059        if !self.status.overflow {
1060            self.program_counter = address;
1061        }
1062    }
1063
1064    fn bvs(&mut self, address: u16) {
1065        if self.status.overflow {
1066            self.program_counter = address;
1067        }
1068    }
1069
1070    // Jump instructions
1071    fn jmp(&mut self, address: u16) {
1072        // step is always incrementing, so if we dont decrement address will be one off what it should be.
1073        self.program_counter = address.wrapping_sub(1);
1074    }
1075
1076    fn jsr(&mut self, address: u16) {
1077        let high_byte = ((self.program_counter) >> 8) as u8;
1078        let low_byte = ((self.program_counter) & 0b11111111) as u8;
1079        self.push_to_stack(high_byte);
1080        self.push_to_stack(low_byte);
1081
1082        self.program_counter = address - 1; // step
1083    }
1084
1085    fn rts(&mut self) {
1086        let low_byte = self.pop_from_stack();
1087        let high_byte = self.pop_from_stack();
1088        self.program_counter = ((high_byte as u16) << 8) | (low_byte as u16);
1089    }
1090
1091    // Interrupts
1092    fn brk(&mut self) {
1093        self.program_counter += 2;
1094        let high_byte = (self.program_counter >> 8) as u8;
1095        let low_byte = (self.program_counter & 0xFF) as u8;
1096        self.push_to_stack(high_byte);
1097        self.push_to_stack(low_byte);
1098        self.status._break = true;
1099        self.push_to_stack(self.status.to_u8());
1100        self.status._break = false;
1101        self.status.interrupt = true;
1102
1103        let new_high_byte = self.bus.read(0xFFFF);
1104        let new_low_byte = self.bus.read(0xFFFE);
1105        let pc = ((new_high_byte as u16) << 8) | new_low_byte as u16;
1106        self.program_counter = pc - 1; // cause of step() always incrementing
1107    }
1108
1109    fn rti(&mut self) {
1110        let mut status = StatusRegister::from_u8(self.pop_from_stack());
1111        status.ignored = true;
1112        status._break = false;
1113        let low_byte = self.pop_from_stack();
1114        let high_byte = self.pop_from_stack();
1115        let program_counter = ((high_byte as u16) << 8) | low_byte as u16;
1116
1117        self.status = status;
1118        self.program_counter = program_counter.wrapping_sub(1);
1119    }
1120
1121    // Other
1122    fn bit(&mut self, operand: u8) {
1123        self.status.negative = (operand & 0b10000000) > 0;
1124        self.status.overflow = (operand & 0b01000000) > 0;
1125
1126        self.status.zero = (operand & self.accumulator) == 0;
1127    }
1128
1129    fn nop(&mut self) {
1130        // its noping time!
1131    }
1132
1133    // Illegal Instructions!
1134    fn alr(&mut self, operand: u8) {
1135        self.and(operand);
1136        self.lsr(0x0, operand, true);
1137    }
1138
1139    fn anc(&mut self, operand: u8) {
1140        self.and(operand);
1141        self.status.carry = (self.accumulator & 0x80) > 0;
1142    }
1143
1144    fn ane(&mut self, operand: u8) {
1145        self.accumulator = (self.accumulator | 0xFF) & self.x & operand;
1146        self.status.negative = self.accumulator & 0x80 > 0;
1147        self.status.zero = self.accumulator == 0;
1148    }
1149
1150    fn arr(&mut self, address: u16, operand: u8) {
1151        self.and(operand);
1152        self.ror(0x0, self.bus.read(address), true);
1153        let bit7_4 = (self.accumulator & 0x80) > 0;
1154        self.status.carry = bit7_4;
1155    }
1156
1157    fn dcp(&mut self, address: u16, operand: u8) {
1158        self.dec(address, operand);
1159        self.cmp(self.bus.read(address));
1160    }
1161
1162    fn isc(&mut self, address: u16, operand: u8) {
1163        self.inc(address, operand);
1164        self.sbc(self.bus.read(address));
1165    }
1166
1167    fn las(&mut self, operand: u8) {
1168        let result = operand & self.stack_pointer;
1169        self.accumulator = result;
1170        self.x = result;
1171        self.stack_pointer = result;
1172
1173        self.status.negative = result & 0x80 > 0;
1174        self.status.zero = result == 0;
1175    }
1176
1177    fn lax(&mut self, operand: u8) {
1178        self.lda(operand);
1179        self.ldx(self.accumulator);
1180    }
1181
1182    fn lxa(&mut self, operand: u8) {
1183        let result = (self.accumulator | 0xFF) & operand;
1184        self.accumulator = result;
1185        self.x = self.accumulator;
1186
1187        self.status.negative = result & 0x80 > 0;
1188        self.status.zero = result == 0;
1189    }
1190
1191    fn rla(&mut self, address: u16, operand: u8) {
1192        self.rol(address, operand, false);
1193        self.and(self.bus.read(address));
1194    }
1195
1196    fn rra(&mut self, address: u16, operand: u8) {
1197        self.ror(address, operand, false);
1198        self.adc(self.bus.read(address));
1199    }
1200
1201    fn sax(&mut self, address: u16) {
1202        self.bus.write(address, self.accumulator & self.x);
1203    }
1204
1205    fn sbx(&mut self, operand: u8) {
1206        self.x = (self.accumulator & self.x).wrapping_sub(operand);
1207        self.status.negative = self.x & 0x80 > 0;
1208        self.status.zero = self.x == 0;
1209    }
1210
1211    fn sha(&mut self, address: u16) {
1212        let high_byte = (((address & 0xFF00) >> 8) + 1) as u8;
1213        self.bus.write(address, self.accumulator & self.x & high_byte);
1214    }   
1215
1216    fn shx(&mut self, address: u16) {
1217        let high_byte = (((address & 0xFF00) >> 8) + 1) as u8;
1218        self.bus.write(address, self.x & high_byte);
1219    }
1220
1221    fn shy(&mut self, address: u16) {
1222        let high_byte = (((address & 0xFF00) >> 8) + 1) as u8;
1223        self.bus.write(address, self.y & high_byte);    
1224    }
1225
1226    fn slo(&mut self, address: u16, operand: u8) {
1227        self.asl(address, operand, false);
1228        self.ora(self.bus.read(address));
1229    }
1230
1231    fn sre(&mut self, address: u16, operand: u8) {
1232        self.lsr(address, operand, false);
1233        self.eor(self.bus.read(address));
1234    }
1235
1236    fn tas(&mut self, address: u16) {
1237        let high_byte = (((address & 0xFF00) >> 8) + 1) as u8;
1238        self.stack_pointer = self.accumulator & self.x;
1239        self.bus.write(address, self.accumulator & self.x & high_byte);
1240    }
1241
1242    fn usbc(&mut self, operand: u8) {
1243        self.sbc(operand);
1244    }
1245}
1246