1use crate::{
2 core::{
3 cpu::Cpu,
4 instruction::{AddressingMode, Instruction, OpCode},
5 },
6 error::CpuError,
7};
8
9impl Cpu {
10 pub(crate) fn decode(&mut self, opcode: u8) -> Result<Instruction, CpuError> {
11 let (opcode, mode, cycles) = match opcode {
12 0x69 => (OpCode::ADC, AddressingMode::immediate(self), 2),
14 0x65 => (OpCode::ADC, AddressingMode::zero_page(self), 3),
15 0x75 => (OpCode::ADC, AddressingMode::zero_page_x(self), 4),
16 0x6D => (OpCode::ADC, AddressingMode::absolute(self), 4),
17 0x7D => (OpCode::ADC, AddressingMode::absolute_x(self), 4),
18 0x79 => (OpCode::ADC, AddressingMode::absolute_y(self), 4),
19 0x61 => (OpCode::ADC, AddressingMode::indirect_x(self), 6),
20 0x71 => (OpCode::ADC, AddressingMode::indirect_y(self), 5),
21 0x29 => (OpCode::AND, AddressingMode::immediate(self), 2),
23 0x25 => (OpCode::AND, AddressingMode::zero_page(self), 3),
24 0x35 => (OpCode::AND, AddressingMode::zero_page_x(self), 4),
25 0x2D => (OpCode::AND, AddressingMode::absolute(self), 4),
26 0x3D => (OpCode::AND, AddressingMode::absolute_x(self), 4),
27 0x39 => (OpCode::AND, AddressingMode::absolute_y(self), 4),
28 0x21 => (OpCode::AND, AddressingMode::indirect_x(self), 6),
29 0x31 => (OpCode::AND, AddressingMode::indirect_y(self), 5),
30 0x0A => (OpCode::ASL, AddressingMode::accumulator(self), 2),
32 0x06 => (OpCode::ASL, AddressingMode::zero_page(self), 5),
33 0x16 => (OpCode::ASL, AddressingMode::zero_page_x(self), 6),
34 0x0E => (OpCode::ASL, AddressingMode::absolute(self), 6),
35 0x1E => (OpCode::ASL, AddressingMode::absolute_x(self), 7),
36 0x24 => (OpCode::BIT, AddressingMode::zero_page(self), 3),
38 0x2C => (OpCode::BIT, AddressingMode::absolute(self), 4),
39 0x10 => (OpCode::BPL, AddressingMode::relative(self), 2),
41 0x30 => (OpCode::BMI, AddressingMode::relative(self), 2),
42 0x50 => (OpCode::BVC, AddressingMode::relative(self), 2),
43 0x70 => (OpCode::BVS, AddressingMode::relative(self), 2),
44 0x90 => (OpCode::BCC, AddressingMode::relative(self), 2),
45 0xB0 => (OpCode::BCS, AddressingMode::relative(self), 2),
46 0xD0 => (OpCode::BNE, AddressingMode::relative(self), 2),
47 0xF0 => (OpCode::BEQ, AddressingMode::relative(self), 2),
48 0x00 => (OpCode::BRK, AddressingMode::implied(self), 7),
50 0xC9 => (OpCode::CMP, AddressingMode::immediate(self), 2),
52 0xC5 => (OpCode::CMP, AddressingMode::zero_page(self), 3),
53 0xD5 => (OpCode::CMP, AddressingMode::zero_page_x(self), 4),
54 0xCD => (OpCode::CMP, AddressingMode::absolute(self), 4),
55 0xDD => (OpCode::CMP, AddressingMode::absolute_x(self), 4),
56 0xD9 => (OpCode::CMP, AddressingMode::absolute_y(self), 4),
57 0xC1 => (OpCode::CMP, AddressingMode::indirect_x(self), 6),
58 0xD1 => (OpCode::CMP, AddressingMode::indirect_y(self), 5),
59 0xE0 => (OpCode::CPX, AddressingMode::immediate(self), 2),
61 0xE4 => (OpCode::CPX, AddressingMode::zero_page(self), 3),
62 0xEC => (OpCode::CPX, AddressingMode::absolute(self), 4),
63 0xC0 => (OpCode::CPY, AddressingMode::immediate(self), 2),
65 0xC4 => (OpCode::CPY, AddressingMode::zero_page(self), 3),
66 0xCC => (OpCode::CPY, AddressingMode::absolute(self), 4),
67 0xC6 => (OpCode::DEC, AddressingMode::zero_page(self), 5),
69 0xD6 => (OpCode::DEC, AddressingMode::zero_page_x(self), 6),
70 0xCE => (OpCode::DEC, AddressingMode::absolute(self), 6),
71 0xDE => (OpCode::DEC, AddressingMode::absolute_x(self), 7),
72 0x49 => (OpCode::EOR, AddressingMode::immediate(self), 2),
74 0x45 => (OpCode::EOR, AddressingMode::zero_page(self), 3),
75 0x55 => (OpCode::EOR, AddressingMode::zero_page_x(self), 4),
76 0x4D => (OpCode::EOR, AddressingMode::absolute(self), 4),
77 0x5D => (OpCode::EOR, AddressingMode::absolute_x(self), 4),
78 0x59 => (OpCode::EOR, AddressingMode::absolute_y(self), 4),
79 0x41 => (OpCode::EOR, AddressingMode::indirect_x(self), 6),
80 0x51 => (OpCode::EOR, AddressingMode::indirect_y(self), 5),
81 0x18 => (OpCode::CLC, AddressingMode::implied(self), 2),
83 0x38 => (OpCode::SEC, AddressingMode::implied(self), 2),
84 0x58 => (OpCode::CLI, AddressingMode::implied(self), 2),
85 0x78 => (OpCode::SEI, AddressingMode::implied(self), 2),
86 0xB8 => (OpCode::CLV, AddressingMode::implied(self), 2),
87 0xD8 => (OpCode::CLD, AddressingMode::implied(self), 2),
88 0xF8 => (OpCode::SED, AddressingMode::implied(self), 2),
89 0xE6 => (OpCode::INC, AddressingMode::zero_page(self), 5),
91 0xF6 => (OpCode::INC, AddressingMode::zero_page_x(self), 6),
92 0xEE => (OpCode::INC, AddressingMode::absolute(self), 6),
93 0xFE => (OpCode::INC, AddressingMode::absolute_x(self), 7),
94 0x4C => (OpCode::JMP, AddressingMode::absolute(self), 3),
96 0x6C => (OpCode::JMP, AddressingMode::indirect(self), 5),
97 0x20 => (OpCode::JSR, AddressingMode::absolute(self), 6),
99 0xA9 => (OpCode::LDA, AddressingMode::immediate(self), 2),
101 0xA5 => (OpCode::LDA, AddressingMode::zero_page(self), 3),
102 0xB5 => (OpCode::LDA, AddressingMode::zero_page_x(self), 4),
103 0xAD => (OpCode::LDA, AddressingMode::absolute(self), 4),
104 0xBD => (OpCode::LDA, AddressingMode::absolute_x(self), 4),
105 0xB9 => (OpCode::LDA, AddressingMode::absolute_y(self), 4),
106 0xA1 => (OpCode::LDA, AddressingMode::indirect_x(self), 6),
107 0xB1 => (OpCode::LDA, AddressingMode::indirect_y(self), 5),
108 0xA2 => (OpCode::LDX, AddressingMode::immediate(self), 2),
110 0xA6 => (OpCode::LDX, AddressingMode::zero_page(self), 3),
111 0xB6 => (OpCode::LDX, AddressingMode::zero_page_y(self), 4),
112 0xAE => (OpCode::LDX, AddressingMode::absolute(self), 4),
113 0xBE => (OpCode::LDX, AddressingMode::absolute_y(self), 4),
114 0xA0 => (OpCode::LDY, AddressingMode::immediate(self), 2),
116 0xA4 => (OpCode::LDY, AddressingMode::zero_page(self), 3),
117 0xB4 => (OpCode::LDY, AddressingMode::zero_page_x(self), 4),
118 0xAC => (OpCode::LDY, AddressingMode::absolute(self), 4),
119 0xBC => (OpCode::LDY, AddressingMode::absolute_x(self), 4),
120 0x4A => (OpCode::LSR, AddressingMode::accumulator(self), 2),
122 0x46 => (OpCode::LSR, AddressingMode::zero_page(self), 5),
123 0x56 => (OpCode::LSR, AddressingMode::zero_page_x(self), 6),
124 0x4E => (OpCode::LSR, AddressingMode::absolute(self), 6),
125 0x5E => (OpCode::LSR, AddressingMode::absolute_x(self), 7),
126 0xEA => (OpCode::NOP, AddressingMode::implied(self), 2),
128 0x09 => (OpCode::ORA, AddressingMode::immediate(self), 2),
130 0x05 => (OpCode::ORA, AddressingMode::zero_page(self), 3),
131 0x15 => (OpCode::ORA, AddressingMode::zero_page_x(self), 4),
132 0x0D => (OpCode::ORA, AddressingMode::absolute(self), 4),
133 0x1D => (OpCode::ORA, AddressingMode::absolute_x(self), 4),
134 0x19 => (OpCode::ORA, AddressingMode::absolute_y(self), 4),
135 0x01 => (OpCode::ORA, AddressingMode::indirect_x(self), 6),
136 0x11 => (OpCode::ORA, AddressingMode::indirect_y(self), 5),
137 0xAA => (OpCode::TAX, AddressingMode::implied(self), 2),
139 0x8A => (OpCode::TXA, AddressingMode::implied(self), 2),
140 0xCA => (OpCode::DEX, AddressingMode::implied(self), 2),
141 0xE8 => (OpCode::INX, AddressingMode::implied(self), 2),
142 0xA8 => (OpCode::TAY, AddressingMode::implied(self), 2),
143 0x98 => (OpCode::TYA, AddressingMode::implied(self), 2),
144 0x88 => (OpCode::DEY, AddressingMode::implied(self), 2),
145 0xC8 => (OpCode::INY, AddressingMode::implied(self), 2),
146 0x2A => (OpCode::ROL, AddressingMode::accumulator(self), 2),
148 0x26 => (OpCode::ROL, AddressingMode::zero_page(self), 5),
149 0x36 => (OpCode::ROL, AddressingMode::zero_page_x(self), 6),
150 0x2E => (OpCode::ROL, AddressingMode::absolute(self), 6),
151 0x3E => (OpCode::ROL, AddressingMode::absolute_x(self), 7),
152 0x6A => (OpCode::ROR, AddressingMode::accumulator(self), 2),
154 0x66 => (OpCode::ROR, AddressingMode::zero_page(self), 5),
155 0x76 => (OpCode::ROR, AddressingMode::zero_page_x(self), 6),
156 0x6E => (OpCode::ROR, AddressingMode::absolute(self), 6),
157 0x7E => (OpCode::ROR, AddressingMode::absolute_x(self), 7),
158 0x40 => (OpCode::RTI, AddressingMode::implied(self), 6),
160 0x60 => (OpCode::RTS, AddressingMode::implied(self), 6),
162 0xE9 => (OpCode::SBC, AddressingMode::immediate(self), 2),
164 0xE5 => (OpCode::SBC, AddressingMode::zero_page(self), 3),
165 0xF5 => (OpCode::SBC, AddressingMode::zero_page_x(self), 4),
166 0xED => (OpCode::SBC, AddressingMode::absolute(self), 4),
167 0xFD => (OpCode::SBC, AddressingMode::absolute_x(self), 4),
168 0xF9 => (OpCode::SBC, AddressingMode::absolute_y(self), 4),
169 0xE1 => (OpCode::SBC, AddressingMode::indirect_x(self), 6),
170 0xF1 => (OpCode::SBC, AddressingMode::indirect_y(self), 5),
171 0x85 => (OpCode::STA, AddressingMode::zero_page(self), 3),
173 0x95 => (OpCode::STA, AddressingMode::zero_page_x(self), 4),
174 0x8D => (OpCode::STA, AddressingMode::absolute(self), 4),
175 0x9D => (OpCode::STA, AddressingMode::absolute_x(self), 5),
176 0x99 => (OpCode::STA, AddressingMode::absolute_y(self), 5),
177 0x81 => (OpCode::STA, AddressingMode::indirect_x(self), 6),
178 0x91 => (OpCode::STA, AddressingMode::indirect_y(self), 6),
179 0x9A => (OpCode::TXS, AddressingMode::implied(self), 2),
181 0xBA => (OpCode::TSX, AddressingMode::implied(self), 2),
182 0x48 => (OpCode::PHA, AddressingMode::implied(self), 3),
183 0x68 => (OpCode::PLA, AddressingMode::implied(self), 4),
184 0x08 => (OpCode::PHP, AddressingMode::implied(self), 3),
185 0x28 => (OpCode::PLP, AddressingMode::implied(self), 4),
186 0x86 => (OpCode::STX, AddressingMode::zero_page(self), 3),
188 0x96 => (OpCode::STX, AddressingMode::zero_page_y(self), 4),
189 0x8E => (OpCode::STX, AddressingMode::absolute(self), 4),
190 0x84 => (OpCode::STY, AddressingMode::zero_page(self), 3),
192 0x94 => (OpCode::STY, AddressingMode::zero_page_x(self), 4),
193 0x8C => (OpCode::STY, AddressingMode::absolute(self), 4),
194 _ => Err(CpuError::InvalidOpCode(opcode))?,
195 };
196
197 let mode = mode?;
198
199 Ok(Instruction { opcode, mode, cycles })
200 }
201}