implemented the INC and DEC family of instructions

This commit is contained in:
2026-08-09 11:06:08 -05:00
parent ce5e94277e
commit 16b51620a6
3 changed files with 268 additions and 3 deletions
+92
View File
@@ -148,6 +148,12 @@ impl Cpu {
0x49 => self.eor_imm(bus), 0x45 => self.eor_zp(bus), 0x55 => self.eor_zpx(bus),
0x4D => self.eor_abs(bus), 0x5D => self.eor_abx(bus), 0x59 => self.eor_aby(bus),
0x41 => self.eor_izx(bus), 0x51 => self.eor_izy(bus),
// Increments
0xE6 => self.inc_zp(bus), 0xF6 => self.inc_zpx(bus), 0xEE => self.inc_abs(bus),
0xFE => self.inc_abx(bus), 0xE8 => self.inx_imp(bus), 0xC8 => self.iny_imp(bus),
// Decrements
0xC6 => self.dec_zp(bus), 0xD6 => self.dec_zpx(bus), 0xCE => self.dec_abs(bus),
0xDE => self.dec_abx(bus), 0xCA => self.dex_imp(bus), 0x88 => self.dey_imp(bus),
_ => panic!("illegal/unkown opcode {opcode:#04X} at {:#06X}", self.pc.wrapping_sub(1)),
};
self.cycles += cycles as u64;
@@ -185,6 +191,9 @@ impl Cpu {
0x1D => 3, /* ORA abx */ 0x19 => 3, /* ORA aby */ 0x01 => 2, /* ORA izx */ 0x11 => 2, /* ORA izy */
0x49 => 2, /* EOR imm */ 0x45 => 2, /* EOR zp */ 0x55 => 2, /* EOR zpx */ 0x4D => 3, /* EOR abs */
0x5D => 3, /* EOR abx */ 0x59 => 3, /* EOR aby */ 0x41 => 2, /* EOR izx */ 0x51 => 2, /* EOR izy */
0xE6 => 2, /* INC zp */ 0xF6 => 2, /* INC zpx */ 0xEE => 3, /* INC abs */ 0xFE => 3, /* INC abx */
0xE8 => 1, /* INX imp */ 0xC8 => 1, /* INY imp */ 0xC6 => 2, /* DEC zp */ 0xD6 => 2, /* DEC zpx */
0xCE => 3, /* DEC abs */ 0xDE => 3, /* DEC abx */ 0xCA => 1, /* DEX imp */ 0x88 => 1, /* DEY imp */
_ => 1, // fallback, would show the invalid/unknown opcode only not its parameters
}
}
@@ -405,6 +414,22 @@ impl Cpu {
base + extra
}
// INC core
fn inc(&mut self, bus: &mut impl Bus, (address, _extra): (u16, u8), base: u8) -> u8 {
let value = self.read(bus, address).wrapping_add(1);
self.write(bus, address, value);
self.set_zp_flags(value);
base // NO + extra — RMW cycles are fixed
}
// DEC core
fn dec(&mut self, bus: &mut impl Bus, (address, _extra): (u16, u8), base: u8) -> u8 {
let value = self.read(bus, address).wrapping_sub(1);
self.write(bus, address, value);
self.set_zp_flags(value);
base // NO + extra — RMW cycles are fixed
}
// NES 6502 opcode -> functions
fn jmp_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0x4C, 3 bytes, 3 cycles
self.pc = self.fetch16(bus);
@@ -968,6 +993,73 @@ impl Cpu {
2
}
// INC variants
fn inc_zp(&mut self, bus: &mut impl Bus) -> u8 { // 0xE6, 2 bytes, 5 cycles
let (address, extra) = self.address_zp(bus);
self.inc(bus, (address, extra), 5)
}
fn inc_zpx(&mut self, bus: &mut impl Bus) -> u8 { // 0xF6, 2 bytes, 6 cycles
let (address, extra) = self.address_zpx(bus);
self.inc(bus, (address, extra), 6)
}
fn inc_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0xEE, 3 bytes, 6 cycles
let (address, extra) = self.address_abs(bus);
self.inc(bus, (address, extra), 6)
}
fn inc_abx(&mut self, bus: &mut impl Bus) -> u8 { // 0xFE, 3 bytes, 7 cycles
let (address, extra) = self.address_abx(bus);
self.inc(bus, (address, extra), 7)
}
// DEC variants
fn dec_zp(&mut self, bus: &mut impl Bus) -> u8 { // 0xC6, 2 bytes, 5 cycles
let (address, extra) = self.address_zp(bus);
self.dec(bus, (address, extra), 5)
}
fn dec_zpx(&mut self, bus: &mut impl Bus) -> u8 { // 0xD6, 2 bytes, 6 cycles
let (address, extra) = self.address_zpx(bus);
self.dec(bus, (address, extra), 6)
}
fn dec_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0xCE, 3 bytes, 6 cycles
let (address, extra) = self.address_abs(bus);
self.dec(bus, (address, extra), 6)
}
fn dec_abx(&mut self, bus: &mut impl Bus) -> u8 { // 0xDE, 3 bytes, 7 cycles
let (address, extra) = self.address_abx(bus);
self.dec(bus, (address, extra), 7)
}
// INC register variants
fn inx_imp(&mut self, _bus: &mut impl Bus) -> u8 { // 0xE8, 1 byte, 2 cycles
self.x = self.x.wrapping_add(1);
self.set_zp_flags(self.x);
2
}
fn iny_imp(&mut self, _bus: &mut impl Bus) -> u8 { // 0xC8, 1 byte, 2 cycles
self.y = self.y.wrapping_add(1);
self.set_zp_flags(self.y);
2
}
// DEC register variants
fn dex_imp(&mut self, _bus: &mut impl Bus) -> u8 { // 0xCA, 1 byte, 2 cycles
self.x = self.x.wrapping_sub(1);
self.set_zp_flags(self.x);
2
}
fn dey_imp(&mut self, _bus: &mut impl Bus) -> u8 { // 0x88, 1 byte, 2 cycles
self.y = self.y.wrapping_sub(1);
self.set_zp_flags(self.y);
2
}
// all branching alternatives here, all 1 bytes
fn bcs_rel(&mut self, bus: &mut impl Bus) -> u8 { self.branch(bus, self.flag(FLAG_CARRY)) } // 0xB0