1use crate::{
2 core::{
3 cpu::{Cpu, StatusFlags},
4 instruction::{AddressingMode, Instruction, OpCode},
5 },
6 error::CpuError,
7};
8
9impl Cpu {
10 pub(crate) fn execute(&mut self, instruction: Instruction) -> Result<u8, CpuError> {
12 let Instruction {
13 opcode,
14 mode,
15 mut cycles,
16 } = instruction;
17
18 let (data, address) = self.interpret_payload(&mode, &mut cycles);
19
20 match opcode {
21 OpCode::ADC => {
22 let input_carry = self.is_flag(StatusFlags::Carry);
23 let (result, carry) = self.a.carrying_add(data, input_carry);
24 let overflow = input_carry != carry; self.set_flag(StatusFlags::Overflow, overflow);
26 self.set_flag(StatusFlags::Carry, carry);
27 self.set_flag(StatusFlags::Zero, result == 0x00);
28 self.set_flag(StatusFlags::Negative, (result & 0x80) == 0x80);
29 self.a = result;
30 }
31 OpCode::AND => {
32 self.a &= data;
33 self.set_flag(StatusFlags::Zero, self.a == 0x00);
34 self.set_flag(StatusFlags::Negative, (self.a & 0x80) == 0x80);
35 }
36 OpCode::ASL => {
37 let shifted = (data as u16) << 1;
38 self.set_flag(StatusFlags::Carry, (shifted & 0xFF00) > 0);
39 self.set_flag(StatusFlags::Zero, (shifted & 0xFF00) > 0);
40 self.set_flag(StatusFlags::Negative, (shifted & 0x0080) == 0x0080);
41 if let AddressingMode::Implied | AddressingMode::Accumulator = mode {
42 self.a = shifted as u8;
43 } else {
44 self.write(address, shifted as u8);
45 }
46 }
47 OpCode::BCC => {
48 if !self.is_flag(StatusFlags::Carry) {
49 cycles += 1;
50 let (addr, overflow) = self.program_counter.overflowing_add(address);
51 if overflow {
52 cycles += 1;
53 }
54 self.program_counter = addr;
55 }
56 }
57 OpCode::BCS => {
58 if self.is_flag(StatusFlags::Carry) {
59 self.branch(address, &mut cycles);
60 }
61 }
62 OpCode::BEQ => {
63 if self.is_flag(StatusFlags::Zero) {
64 self.branch(address, &mut cycles);
65 }
66 }
67 OpCode::BIT => {
68 let temp = self.a & data;
69 self.set_flag(StatusFlags::Overflow, temp == 0x00);
70 self.set_flag(StatusFlags::Zero, data & (1 << 7) == (1 << 7));
71 self.set_flag(StatusFlags::Negative, data & (1 << 6) == (1 << 6));
72 }
73 OpCode::BMI => {
74 if self.is_flag(StatusFlags::Negative) {
75 self.branch(address, &mut cycles);
76 }
77 }
78 OpCode::BNE => {
79 if !self.is_flag(StatusFlags::Zero) {
80 self.branch(address, &mut cycles);
81 }
82 }
83 OpCode::BPL => {
84 if !self.is_flag(StatusFlags::Negative) {
85 self.branch(address, &mut cycles);
86 }
87 }
88 OpCode::BRK => {
89 self.set_flag(StatusFlags::Interrupt, true);
90 let [lo, hi] = self.program_counter.to_le_bytes();
91 self.push(hi);
92 self.push(lo);
93 self.set_flag(StatusFlags::Break, true);
94 self.push(self.status.bits());
95 self.set_flag(StatusFlags::Break, false);
96
97 let lo = self.read(Self::INTERRUPT_ADDRESS);
98 let hi = self.read(Self::INTERRUPT_ADDRESS + 1);
99 self.program_counter = u16::from_le_bytes([lo, hi]);
100 }
101 OpCode::BVC => {
102 if !self.is_flag(StatusFlags::Overflow) {
103 self.branch(address, &mut cycles);
104 }
105 }
106 OpCode::BVS => {
107 if self.is_flag(StatusFlags::Overflow) {
108 self.branch(address, &mut cycles);
109 }
110 }
111 OpCode::CLC => {
112 self.set_flag(StatusFlags::Carry, false);
113 }
114 OpCode::CLD => {
115 self.set_flag(StatusFlags::Decimal, false);
116 }
117 OpCode::CLI => {
118 self.set_flag(StatusFlags::Interrupt, false);
119 }
120 OpCode::CLV => {
121 self.set_flag(StatusFlags::Overflow, false);
122 }
123 OpCode::CMP => {
124 let temp = self.a - data;
125 self.set_flag(StatusFlags::Carry, self.a >= data);
126 self.set_flag(StatusFlags::Zero, temp == 0x00);
127 self.set_flag(StatusFlags::Negative, (temp & 0x80) == 0x80);
128 }
129 OpCode::CPX => {
130 let temp = self.x - data;
131 self.set_flag(StatusFlags::Carry, self.a >= data);
132 self.set_flag(StatusFlags::Zero, temp == 0x00);
133 self.set_flag(StatusFlags::Negative, (temp & 0x80) == 0x80);
134 }
135 OpCode::CPY => {
136 let temp = self.y - data;
137 self.set_flag(StatusFlags::Carry, self.a >= data);
138 self.set_flag(StatusFlags::Zero, temp == 0x00);
139 self.set_flag(StatusFlags::Negative, (temp & 0x80) == 0x80);
140 }
141 OpCode::DEC => {
142 let temp = data - 1;
143 self.write(address, temp);
144 self.set_flag(StatusFlags::Zero, temp == 0x00);
145 self.set_flag(StatusFlags::Negative, (temp & 0x80) == 0x80);
146 }
147 OpCode::DEX => {
148 self.x -= 1;
149 self.set_flag(StatusFlags::Zero, self.x == 0x00);
150 self.set_flag(StatusFlags::Negative, (self.x & 0x80) == 0x80);
151 }
152 OpCode::DEY => {
153 self.y -= 1;
154 self.set_flag(StatusFlags::Zero, self.y == 0x00);
155 self.set_flag(StatusFlags::Negative, (self.y & 0x80) == 0x80);
156 }
157 OpCode::EOR => {
158 self.a ^= data;
159 self.set_flag(StatusFlags::Zero, self.a == 0x00);
160 self.set_flag(StatusFlags::Negative, (self.a & 0x80) == 0x80);
161 }
162 OpCode::INC => {
163 let temp = data + 1;
164 self.write(address, temp);
165 self.set_flag(StatusFlags::Zero, temp == 0x00);
166 self.set_flag(StatusFlags::Negative, (temp & 0x80) == 0x80);
167 }
168 OpCode::INX => {
169 self.x += 1;
170 self.set_flag(StatusFlags::Zero, self.x == 0x00);
171 self.set_flag(StatusFlags::Negative, (self.x & 0x80) == 0x80);
172 }
173 OpCode::INY => {
174 self.y += 1;
175 self.set_flag(StatusFlags::Zero, self.y == 0x00);
176 self.set_flag(StatusFlags::Negative, (self.y & 0x80) == 0x80);
177 }
178 OpCode::JMP => {
179 self.program_counter = address;
180 }
181 OpCode::JSR => {
182 let [lo, hi] = self.program_counter.to_le_bytes();
184 self.push(hi);
185 self.push(lo);
186 self.program_counter = address;
187 }
188 OpCode::LDA => {
189 self.a = data;
190 self.set_flag(StatusFlags::Zero, self.a == 0x00);
191 self.set_flag(StatusFlags::Negative, (self.a & 0x80) == 0x80);
192 }
193 OpCode::LDX => {
194 self.x = data;
195 self.set_flag(StatusFlags::Zero, self.x == 0x00);
196 self.set_flag(StatusFlags::Negative, (self.x & 0x80) == 0x80);
197 }
198 OpCode::LDY => {
199 self.y = data;
200 self.set_flag(StatusFlags::Zero, self.y == 0x00);
201 self.set_flag(StatusFlags::Negative, (self.y & 0x80) == 0x80);
202 }
203 OpCode::LSR => {
204 self.set_flag(StatusFlags::Carry, (data & 0x01) == 0x01);
205 let temp = data >> 1;
206 self.set_flag(StatusFlags::Zero, temp == 0x00);
207 self.set_flag(StatusFlags::Negative, (temp & 0x80) == 0x80);
208 if let AddressingMode::Implied | AddressingMode::Accumulator = mode {
209 self.a = temp;
210 } else {
211 self.write(address, temp);
212 }
213 }
214 OpCode::NOP => (),
215 OpCode::ORA => {
216 self.a |= data;
217 self.set_flag(StatusFlags::Zero, self.a == 0x00);
218 self.set_flag(StatusFlags::Negative, (self.a & 0x80) == 0x80);
219 }
220 OpCode::PHA => {
221 self.push(self.a);
222 }
223 OpCode::PHP => {
224 self.push((self.status | StatusFlags::Unused | StatusFlags::Break).bits());
225 self.set_flag(StatusFlags::Break, false);
226 self.set_flag(StatusFlags::Unused, false);
227 }
228 OpCode::PLA => {
229 self.a = self.pop();
230 self.set_flag(StatusFlags::Zero, self.a == 0x00);
231 self.set_flag(StatusFlags::Negative, (self.a & 0x80) == 0x80);
232 }
233 OpCode::PLP => {
234 self.status = self.pop().try_into().map_err(|e| CpuError::Other(format!("{e}")))?;
235 self.set_flag(StatusFlags::Unused, true);
236 }
237 OpCode::ROL => {
238 let carry = self.is_flag(StatusFlags::Carry) as u8;
239 let new_carry = (data & 0x80) == 0x80;
240 let temp = (data << 1) | carry;
241 self.set_flag(StatusFlags::Carry, new_carry);
242 self.set_flag(StatusFlags::Zero, temp == 0x00);
243 self.set_flag(StatusFlags::Negative, (temp & 0x80) == 0x80);
244 if let AddressingMode::Implied | AddressingMode::Accumulator = mode {
245 self.a = temp;
246 } else {
247 self.write(address, temp);
248 }
249 }
250 OpCode::ROR => {
251 let carry = self.is_flag(StatusFlags::Carry) as u8;
252 let new_carry = (data & 0x01) == 0x01;
253 let temp = (carry << 7) | (data >> 1);
254 self.set_flag(StatusFlags::Carry, new_carry);
255 self.set_flag(StatusFlags::Zero, temp == 0x00);
256 self.set_flag(StatusFlags::Negative, (temp & 0x80) == 0x80);
257 if let AddressingMode::Implied | AddressingMode::Accumulator = mode {
258 self.a = temp;
259 } else {
260 self.write(address, temp);
261 }
262 }
263 OpCode::RTI => {
264 self.status = self.pop().try_into().map_err(|e| CpuError::Other(format!("{e}")))?;
265 self.status.toggle(StatusFlags::Break);
266 self.status.toggle(StatusFlags::Unused);
267
268 let lo = self.pop();
269 let hi = self.pop();
270 self.program_counter = u16::from_le_bytes([lo, hi]);
271 }
272 OpCode::RTS => {
273 let lo = self.pop();
274 let hi = self.pop();
275 self.program_counter = u16::from_le_bytes([lo, hi]);
276 }
277 OpCode::SBC => {
278 let input_data = !data;
279 let input_carry = self.is_flag(StatusFlags::Carry);
280 let (result, carry) = self.a.carrying_add(input_data, input_carry);
281 let overflow = input_carry != carry; self.set_flag(StatusFlags::Overflow, overflow);
283 self.set_flag(StatusFlags::Carry, carry);
284 self.set_flag(StatusFlags::Zero, result == 0x00);
285 self.set_flag(StatusFlags::Negative, (result & 0x80) == 0x80);
286 self.a = result;
287 }
288 OpCode::SEC => {
289 self.set_flag(StatusFlags::Carry, true);
290 }
291 OpCode::SED => {
292 self.set_flag(StatusFlags::Decimal, true);
293 }
294 OpCode::SEI => {
295 self.set_flag(StatusFlags::Interrupt, true);
296 }
297 OpCode::STA => {
298 self.write(address, self.a);
299 }
300 OpCode::STX => {
301 self.write(address, self.x);
302 }
303 OpCode::STY => {
304 self.write(address, self.y);
305 }
306 OpCode::TAX => {
307 self.x = self.a;
308 self.set_flag(StatusFlags::Zero, self.x == 0x00);
309 self.set_flag(StatusFlags::Negative, (self.x & 0x80) == 0x80);
310 }
311 OpCode::TAY => {
312 self.y = self.a;
313 self.set_flag(StatusFlags::Zero, self.y == 0x00);
314 self.set_flag(StatusFlags::Negative, (self.y & 0x80) == 0x80);
315 }
316 OpCode::TSX => {
317 self.x = self.stack_ptr;
318 self.set_flag(StatusFlags::Zero, self.x == 0x00);
319 self.set_flag(StatusFlags::Negative, (self.x & 0x80) == 0x80);
320 }
321 OpCode::TXA => {
322 self.a = self.x;
323 self.set_flag(StatusFlags::Zero, self.a == 0x00);
324 self.set_flag(StatusFlags::Negative, (self.a & 0x80) == 0x80);
325 }
326 OpCode::TXS => {
327 self.stack_ptr = self.x;
328 }
329 OpCode::TYA => {
330 self.a = self.y;
331 self.set_flag(StatusFlags::Zero, self.a == 0x00);
332 self.set_flag(StatusFlags::Negative, (self.a & 0x80) == 0x80);
333 }
334 }
335
336 Ok(cycles)
337 }
338
339 fn interpret_payload(&mut self, mode: &AddressingMode, cycles: &mut u8) -> (u8, u16) {
340 let address = match mode {
341 AddressingMode::Accumulator => self.a as u16,
342 AddressingMode::Implied => {
343 return (self.a, 0);
344 }
345 AddressingMode::Immediate(value) => {
346 return (*value, self.program_counter - 1);
347 }
348 AddressingMode::Relative(addr) => {
349 let mut address = *addr as u16;
350 if (address & 0x80) == 0x80 {
351 address |= 0xFF00;
354 }
355 address
356 }
357 AddressingMode::ZeroPage(addr) => *addr as u16 & 0x00FF,
358 AddressingMode::ZeroPageX(addr) => (addr + self.x as u16) & 0x00FF,
359 AddressingMode::ZeroPageY(addr) => (addr + self.y as u16) & 0x00FF,
360 AddressingMode::Absolute(addr) => *addr,
361 AddressingMode::AbsoluteX(addr) => {
362 let (addr, overflow) = addr.overflowing_add(self.x as u16);
363 if overflow {
364 *cycles += 1;
365 }
366 addr
367 }
368 AddressingMode::AbsoluteY(addr) => {
369 let (addr, overflow) = addr.overflowing_add(self.y as u16);
370 if overflow {
371 *cycles += 1;
372 }
373 addr
374 }
375 AddressingMode::Indirect(ptr) => {
376 if (ptr & 0x00FF) == 0x00FF {
377 let lo = self.read(*ptr);
379 let hi = self.read(ptr & 0xFF00);
380 u16::from_le_bytes([lo, hi])
381 } else {
382 let lo = self.read(*ptr);
384 let hi = self.read(ptr + 1);
385 u16::from_le_bytes([lo, hi])
386 }
387 }
388 AddressingMode::IndirectX(ptr) => {
389 let lo = self.read((ptr + self.x as u16) & 0x00FF);
390 let hi = self.read((ptr + self.x as u16 + 1) & 0x00FF);
391 u16::from_le_bytes([lo, hi])
392 }
393 AddressingMode::IndirectY(ptr) => {
394 let lo = self.read((ptr) & 0x00FF);
395 let hi = self.read((ptr + 1) & 0x00FF);
396 let (addr, overflow) = u16::from_le_bytes([lo, hi]).overflowing_add(self.y as u16);
397 if overflow {
398 *cycles += 1;
399 }
400 addr
401 }
402 };
403
404 let data = self.read(address);
405
406 (data, address)
407 }
408
409 fn branch(&mut self, payload: u16, cycles: &mut u8) {
410 *cycles += 1;
411 let (addr, overflow) = self.program_counter.overflowing_add(payload);
412 if overflow {
413 *cycles += 1;
414 }
415 self.program_counter = addr;
416 }
417}