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 ADC,
54 AND,
56 ASL,
58 BCC,
60 BCS,
62 BEQ,
64 BIT,
66 BMI,
68 BNE,
70 BPL,
72 BRK,
74 BVC,
76 BVS,
78 CLC,
80 CLD,
82 CLI,
84 CLV,
86 CMP,
88 CPX,
90 CPY,
92 DEC,
94 DEX,
96 DEY,
98 EOR,
100 INC,
102 INX,
104 INY,
106 JMP,
108 JSR,
110 LDA,
112 LDX,
114 LDY,
116 LSR,
118 NOP,
120 ORA,
122 PHA,
124 PHP,
126 PLA,
128 PLP,
130 ROL,
132 ROR,
134 RTS,
136 RTI,
138 SBC,
140 SEC,
142 SED,
144 SEI,
146 STA,
148 STX,
150 STY,
152 TAX,
154 TAY,
156 TSX,
158 TXA,
160 TXS,
162 TYA,
164
165 ALR,
169 ANC,
171 ANE,
173 ARR,
175 DCP,
177 ISC,
179 LAS,
181 LAX,
183 LXA,
185 RLA,
187 RRA,
189 SAX,
191 SBX,
193 SHA,
195 SHX,
197 SHY,
199 SLO,
201 SRE,
203 TAS,
205 USBC,
207 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#[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 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 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#[derive(Debug, Clone, Copy)]
284pub enum JamBehavior {
285 Jam,
287 Nop,
289 Panic
291}
292
293#[derive(Debug, Clone, Copy)]
295pub enum IllegalBehavior {
296 Execute,
298 Nop,
300 Panic
302}
303
304#[derive(Debug, Clone, Copy)]
306pub struct CpuConfig {
307 pub bcd_support: bool,
310 pub jam_behavior: JamBehavior,
312 pub illegal_behavior: IllegalBehavior
314}
315
316impl 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
344pub enum CpuStepReturn {
346 Ok(usize),
348 Jam
352}
353
354pub 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 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 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 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 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 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 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 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 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 _ => {
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 _ => 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 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 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 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 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 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 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 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 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 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 fn jmp(&mut self, address: u16) {
1072 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; }
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 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; }
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 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 }
1132
1133 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