Added 10 more opcodes into the CPU interpreter

This commit is contained in:
2026-08-08 14:42:38 -05:00
parent faef20555b
commit a1ff5f280f
3 changed files with 140 additions and 9 deletions
+89 -4
View File
@@ -99,6 +99,16 @@ impl Cpu {
0x4C => self.jmp_abs(bus),
0xA2 => self.ldx_imm(bus),
0x86 => self.stx_zp(bus),
0x20 => self.jsr_abs(bus),
0x60 => self.rts_imp(bus),
0x48 => self.pha_imp(bus),
0x68 => self.pla_imp(bus),
0x08 => self.php_imp(bus),
0x28 => self.plp_imp(bus),
0x40 => self.rti_imp(bus),
0x00 => self.brk_imp(bus),
0xEA => self.nop_imp(bus),
0x38 => self.sec_imp(bus),
_ => panic!("illegal/unkown opcode {opcode:#04X} at {:#06X}", self.pc.wrapping_sub(1)),
};
self.cycles += cycles as u64;
@@ -182,30 +192,105 @@ impl Cpu {
}
// NES 6502 opcode -> functions
fn jmp_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0x4C, 3 cycles
fn jmp_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0x4C, 3 bytes, 3 cycles
self.pc = self.fetch16(bus);
3
}
fn ldx_imm(&mut self, bus: &mut impl Bus) -> u8 { // 0xA2, 2 cycles
fn ldx_imm(&mut self, bus: &mut impl Bus) -> u8 { // 0xA2, 2 bytes, 2 cycles
self.x = self.fetch(bus);
self.set_zp_flags(self.x);
2
}
fn stx_zp(&mut self, bus: &mut impl Bus) -> u8 { // 0x86, 3 cycles
fn stx_zp(&mut self, bus: &mut impl Bus) -> u8 { // 0x86, 2 bytes, 3 cycles
let (addr, _) = self.address_zp(bus);
self.write(bus, addr, self.x);
3
}
fn jsr_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0x20, 3 bytes, 6 cycles
let target = self.fetch16(bus);
let ret = self.pc.wrapping_sub(1);
self.push(bus, (ret >> 8) as u8);
self.push(bus, (ret &0xFF) as u8);
self.pc = target;
6
}
fn rts_imp(&mut self, bus: &mut impl Bus) -> u8 { // 0x60, 1 byte, 6 cycles
let low = self.pop(bus) as u16;
let high = self.pop(bus) as u16;
self.pc = (high << 8 | low).wrapping_add(1);
6
}
fn pha_imp(&mut self, bus: &mut impl Bus) -> u8 { // 0x48, 1 byte, 3 cycles
self.push(bus, self.a);
3
}
fn pla_imp(&mut self, bus: &mut impl Bus) -> u8 { // 0x68, 1 byte, 4 cycles
self.a = self.pop(bus);
self.set_zp_flags(self.a);
4
}
fn php_imp(&mut self, bus: &mut impl Bus) -> u8 { // 0x08, 1 byte, 3 cycles; B-flag model: B exists only in the pushed copy
self.push(bus, self.p | FLAG_BREAK);
3
}
fn plp_imp(&mut self, bus: &mut impl Bus) -> u8 { // 0x28, 1 byte, 4 cycles
self.p = (self.pop(bus) & !FLAG_BREAK) | FLAG_UNUSED;
4
}
fn rti_imp(&mut self, bus: &mut impl Bus) -> u8 { // 0x40, 1 byte, 6 cycles
self.p = (self.pop(bus) & !FLAG_BREAK) | FLAG_UNUSED;
let low: u16 = self.pop(bus) as u16;
let high: u16 = self.pop(bus) as u16;
self.pc = high << 8 | low;
6
}
fn brk_imp(&mut self, bus: &mut impl Bus) -> u8 { // 0x00, 1 byte, 7 cycles
self.pc = self.pc.wrapping_add(1); // Skip padding byte
let ret = self.pc;
self.push(bus, (ret >> 8) as u8);
self.push(bus, (ret & 0xFF) as u8);
self.push(bus, self.p | FLAG_BREAK);
self.set_flag(FLAG_INTERRUPT);
self.pc = self.read16(bus, 0xFFFE); // IRQ vector
7
}
fn nop_imp(&mut self, _bus: &mut impl Bus) -> u8 { // 0xEA, 1 byte, 2 cycles
2
}
fn sec_imp(&mut self, _bus: &mut impl Bus) -> u8 { // 0x38, 1 byte, 2 cycles
self.set_flag(FLAG_CARRY);
2
}
// NES 6502 opcode length table/matcher
fn opcode_len(opcode: u8) -> u8 {
match opcode {
0x4C => 3, // JMP abs
0xA2 => 2, // LDX imm
0x86 => 2, // STX zp
_ => 1, // fallback, would show the invalid/unknown opcode only
0x20 => 3, // JSR abs
0x60 => 1, // RTS imp
0x48 => 1, // PHA imp
0x68 => 1, // PLA imp
0x08 => 1, // PHP imp
0x28 => 1, // PLP imp
0x40 => 1, // RTI imp
0x00 => 1, // BRK imp
0xEA => 1, // NOP
0x38 => 1, // SEC imp
_ => 1, // fallback, would show the invalid/unknown opcode only not its parameters
}
}