implemented the CMP and CPx family of instructions but these are untested
This commit is contained in:
+176
-22
@@ -152,6 +152,20 @@ impl Cpu {
|
||||
0x84 => self.sty_zp(bus),
|
||||
0x94 => self.sty_zpx(bus),
|
||||
0x8C => self.sty_abs(bus),
|
||||
0xC9 => self.cmp_imm(bus),
|
||||
0xC5 => self.cmp_zp(bus),
|
||||
0xD5 => self.cmp_zpx(bus),
|
||||
0xCD => self.cmp_abs(bus),
|
||||
0xDD => self.cmp_abx(bus),
|
||||
0xD9 => self.cmp_aby(bus),
|
||||
0xC1 => self.cmp_izx(bus),
|
||||
0xD1 => self.cmp_izy(bus),
|
||||
0xE0 => self.cpx_imm(bus),
|
||||
0xE4 => self.cpx_zp(bus),
|
||||
0xEC => self.cpx_abs(bus),
|
||||
0xC0 => self.cpy_imm(bus),
|
||||
0xC4 => self.cpy_zp(bus),
|
||||
0xCC => self.cpy_abs(bus),
|
||||
_ => panic!("illegal/unkown opcode {opcode:#04X} at {:#06X}", self.pc.wrapping_sub(1)),
|
||||
};
|
||||
self.cycles += cycles as u64;
|
||||
@@ -284,6 +298,33 @@ impl Cpu {
|
||||
base + extra
|
||||
}
|
||||
|
||||
// shared cores for CMP and CPx instructions
|
||||
fn cmp(&mut self, bus: &mut impl Bus, (address, extra): (u16, u8), base: u8) -> u8 {
|
||||
let value = self.read(bus, address);
|
||||
let result = self.a.wrapping_sub(value);
|
||||
if self.a >= value { self.set_flag(FLAG_CARRY); }
|
||||
else { self.clear_flag(FLAG_CARRY); }
|
||||
self.set_zp_flags(result);
|
||||
base + extra
|
||||
}
|
||||
fn cpx(&mut self, bus: &mut impl Bus, (address, extra): (u16, u8), base: u8) -> u8 {
|
||||
let value = self.read(bus, address);
|
||||
let result = self.x.wrapping_sub(value);
|
||||
if self.x >= value { self.set_flag(FLAG_CARRY); }
|
||||
else { self.clear_flag(FLAG_CARRY); }
|
||||
self.set_zp_flags(result);
|
||||
base + extra
|
||||
}
|
||||
fn cpy(&mut self, bus: &mut impl Bus, (address, extra): (u16, u8), base: u8) -> u8 {
|
||||
let value = self.read(bus, address);
|
||||
let result = self.y.wrapping_sub(value);
|
||||
if self.y >= value { self.set_flag(FLAG_CARRY); }
|
||||
else { self.clear_flag(FLAG_CARRY); }
|
||||
self.set_zp_flags(result);
|
||||
base + extra
|
||||
}
|
||||
|
||||
|
||||
// NES 6502 opcode -> functions
|
||||
fn jmp_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0x4C, 3 bytes, 3 cycles
|
||||
self.pc = self.fetch16(bus);
|
||||
@@ -416,37 +457,37 @@ impl Cpu {
|
||||
}
|
||||
// LDX alternatives
|
||||
fn ldx_zp(&mut self, bus: &mut impl Bus) -> u8 { // 0xA6, 2 bytes
|
||||
let (addr, extra) = self.address_zp(bus);
|
||||
self.ldx(bus, (addr, extra), 3)
|
||||
let (address, extra) = self.address_zp(bus);
|
||||
self.ldx(bus, (address, extra), 3)
|
||||
}
|
||||
fn ldx_zpy(&mut self, bus: &mut impl Bus) -> u8 { // 0xB6, 2 bytes
|
||||
let (addr, extra) = self.address_zpy(bus);
|
||||
self.ldx(bus, (addr, extra), 4)
|
||||
let (address, extra) = self.address_zpy(bus);
|
||||
self.ldx(bus, (address, extra), 4)
|
||||
}
|
||||
fn ldx_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0xAE, 3 bytes
|
||||
let (addr, extra) = self.address_abs(bus);
|
||||
self.ldx(bus, (addr, extra), 4)
|
||||
let (address, extra) = self.address_abs(bus);
|
||||
self.ldx(bus, (address, extra), 4)
|
||||
}
|
||||
fn ldx_aby(&mut self, bus: &mut impl Bus) -> u8 { // 0xBE, 3 bytes
|
||||
let (addr, extra) = self.address_aby(bus);
|
||||
self.ldx(bus, (addr, extra), 4)
|
||||
let (address, extra) = self.address_aby(bus);
|
||||
self.ldx(bus, (address, extra), 4)
|
||||
}
|
||||
// LDY alternatives
|
||||
fn ldy_zp(&mut self, bus: &mut impl Bus) -> u8 { // 0xA4, 2 bytes
|
||||
let (addr, extra) = self.address_zp(bus);
|
||||
self.ldy(bus, (addr, extra), 3)
|
||||
let (address, extra) = self.address_zp(bus);
|
||||
self.ldy(bus, (address, extra), 3)
|
||||
}
|
||||
fn ldy_zpx(&mut self, bus: &mut impl Bus) -> u8 { // 0xB4, 2 bytes
|
||||
let (addr, extra) = self.address_zpx(bus);
|
||||
self.ldy(bus, (addr, extra), 4)
|
||||
let (address, extra) = self.address_zpx(bus);
|
||||
self.ldy(bus, (address, extra), 4)
|
||||
}
|
||||
fn ldy_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0xAC, 3 bytes
|
||||
let (addr, extra) = self.address_abs(bus);
|
||||
self.ldy(bus, (addr, extra), 4)
|
||||
let (address, extra) = self.address_abs(bus);
|
||||
self.ldy(bus, (address, extra), 4)
|
||||
}
|
||||
fn ldy_abx(&mut self, bus: &mut impl Bus) -> u8 { // 0xBC, 3 bytes
|
||||
let (addr, extra) = self.address_abx(bus);
|
||||
self.ldy(bus, (addr, extra), 4)
|
||||
let (address, extra) = self.address_abx(bus);
|
||||
self.ldy(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
// imm variants for LDx
|
||||
@@ -473,56 +514,155 @@ impl Cpu {
|
||||
let (address, extra) = self.address_zp(bus);
|
||||
self.sta(bus, (address, extra), 3)
|
||||
}
|
||||
|
||||
fn sta_zpx(&mut self, bus: &mut impl Bus) -> u8 { // 0x95, 2 bytes, 4 cycles
|
||||
let (address, extra) = self.address_zpx(bus);
|
||||
self.sta(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn sta_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0x8D, 3 bytes, 4 cycles
|
||||
let (address, extra) = self.address_abs(bus);
|
||||
self.sta(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn sta_abx(&mut self, bus: &mut impl Bus) -> u8 { // 0x9D, 3 bytes, 4 cycles
|
||||
let (address, extra) = self.address_abx(bus);
|
||||
self.sta(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn sta_aby(&mut self, bus: &mut impl Bus) -> u8 { // 0x99, 3 bytes, 4 cycles
|
||||
let (address, extra) = self.address_aby(bus);
|
||||
self.sta(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn sta_izx(&mut self, bus: &mut impl Bus) -> u8 { // 0x81, 2 bytes, 6 cycles
|
||||
let (address, extra) = self.address_izx(bus);
|
||||
self.sta(bus, (address, extra), 6)
|
||||
}
|
||||
|
||||
fn sta_izy(&mut self, bus: &mut impl Bus) -> u8 { // 0x91, 2 bytes, 5 cycles
|
||||
let (address, extra) = self.address_izy(bus);
|
||||
self.sta(bus, (address, extra), 5)
|
||||
}
|
||||
|
||||
// STX variants
|
||||
fn stx_zp(&mut self, bus: &mut impl Bus) -> u8 { // 0x86, 2 bytes, 3 cycles
|
||||
let (address, extra) = self.address_zp(bus);
|
||||
self.stx(bus, (address, extra), 3)
|
||||
}
|
||||
|
||||
fn stx_zpy(&mut self, bus: &mut impl Bus) -> u8 { // 0x96, 2 bytes, 4 cycles
|
||||
let (address, extra) = self.address_zpy(bus);
|
||||
self.stx(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn stx_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0x8E, 3 bytes, 4 cycles
|
||||
let (address, extra) = self.address_abs(bus);
|
||||
self.stx(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
// STY variants
|
||||
fn sty_zp(&mut self, bus: &mut impl Bus) -> u8 { // 0x84, 2 bytes, 3 cycles
|
||||
let (addr, extra) = self.address_zp(bus);
|
||||
self.sty(bus, (addr, extra), 3)
|
||||
let (address, extra) = self.address_zp(bus);
|
||||
self.sty(bus, (address, extra), 3)
|
||||
}
|
||||
|
||||
fn sty_zpx(&mut self, bus: &mut impl Bus) -> u8 { // 0x94, 2 bytes, 4 cycles
|
||||
let (addr, extra) = self.address_zpx(bus);
|
||||
self.sty(bus, (addr, extra), 4)
|
||||
let (address, extra) = self.address_zpx(bus);
|
||||
self.sty(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn sty_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0x8C, 3 bytes, 4 cycles
|
||||
let (addr, extra) = self.address_abs(bus);
|
||||
self.sty(bus, (addr, extra), 4)
|
||||
let (address, extra) = self.address_abs(bus);
|
||||
self.sty(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
// CMP variants
|
||||
fn cmp_zp(&mut self, bus: &mut impl Bus) -> u8 { // 0xC5, 2 bytes, 3 cycles
|
||||
let (address, extra) = self.address_zp(bus);
|
||||
self.cmp(bus, (address, extra), 3)
|
||||
}
|
||||
|
||||
fn cmp_zpx(&mut self, bus: &mut impl Bus) -> u8 { // 0xD5, 2 bytes, 4 cycles
|
||||
let (address, extra) = self.address_zpx(bus);
|
||||
self.cmp(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn cmp_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0xCD, 3 bytes, 4 cycles
|
||||
let (address, extra) = self.address_abs(bus);
|
||||
self.cmp(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn cmp_abx(&mut self, bus: &mut impl Bus) -> u8 { // 0xDD, 3 bytes, 4 cycles
|
||||
let (address, extra) = self.address_abx(bus);
|
||||
self.cmp(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn cmp_aby(&mut self, bus: &mut impl Bus) -> u8 { // 0xD9, 3 bytes, 4 cycles
|
||||
let (address, extra) = self.address_aby(bus);
|
||||
self.cmp(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
fn cmp_izx(&mut self, bus: &mut impl Bus) -> u8 { // 0xC1, 2 bytes, 6 cycles
|
||||
let (address, extra) = self.address_izx(bus);
|
||||
self.cmp(bus, (address, extra), 6)
|
||||
}
|
||||
|
||||
fn cmp_izy(&mut self, bus: &mut impl Bus) -> u8 { // 0xD1, 2 bytes, 5 cycles
|
||||
let (address, extra) = self.address_izy(bus);
|
||||
self.cmp(bus, (address, extra), 5)
|
||||
}
|
||||
|
||||
// CPX variants
|
||||
fn cpx_zp(&mut self, bus: &mut impl Bus) -> u8 { // 0xE4, 2 bytes, 3 cycles
|
||||
let (address, extra) = self.address_zp(bus);
|
||||
self.cpx(bus, (address, extra), 3)
|
||||
}
|
||||
|
||||
fn cpx_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0xEC, 3 bytes, 4 cycles
|
||||
let (address, extra) = self.address_abs(bus);
|
||||
self.cpx(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
// CPY variants
|
||||
fn cpy_zp(&mut self, bus: &mut impl Bus) -> u8 { // 0xC4, 2 bytes, 3 cycles
|
||||
let (address, extra) = self.address_zp(bus);
|
||||
self.cpy(bus, (address, extra), 3)
|
||||
}
|
||||
|
||||
fn cpy_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0xCC, 3 bytes, 4 cycles
|
||||
let (address, extra) = self.address_abs(bus);
|
||||
self.cpy(bus, (address, extra), 4)
|
||||
}
|
||||
|
||||
// CMP / CPx immediate mode variants
|
||||
fn cmp_imm(&mut self, bus: &mut impl Bus) -> u8 { // 0xC9, 2 bytes, 2 cycles
|
||||
let value = self.fetch(bus);
|
||||
let result = self.a.wrapping_sub(value);
|
||||
if self.a >= value { self.set_flag(FLAG_CARRY); }
|
||||
else { self.clear_flag(FLAG_CARRY); }
|
||||
self.set_zp_flags(result);
|
||||
2
|
||||
}
|
||||
|
||||
fn cpx_imm(&mut self, bus: &mut impl Bus) -> u8 { // 0xE0, 2 bytes, 2 cycles
|
||||
let value = self.fetch(bus);
|
||||
let result = self.x.wrapping_sub(value);
|
||||
if self.x >= value { self.set_flag(FLAG_CARRY); }
|
||||
else { self.clear_flag(FLAG_CARRY); }
|
||||
self.set_zp_flags(result);
|
||||
2
|
||||
}
|
||||
|
||||
fn cpy_imm(&mut self, bus: &mut impl Bus) -> u8 { // 0xC0, 2 bytes, 2 cycles
|
||||
let value = self.fetch(bus);
|
||||
let result = self.y.wrapping_sub(value);
|
||||
if self.y >= value { self.set_flag(FLAG_CARRY); }
|
||||
else { self.clear_flag(FLAG_CARRY); }
|
||||
self.set_zp_flags(result);
|
||||
2
|
||||
}
|
||||
|
||||
|
||||
|
||||
// all branching alternatives here all 1 bytes
|
||||
@@ -594,6 +734,20 @@ impl Cpu {
|
||||
0x84 => 2, // STY zp
|
||||
0x94 => 2, // STY zpx
|
||||
0x8C => 3, // STY abs
|
||||
0xC9 => 2, // CMP imm
|
||||
0xC5 => 2, // CMP zp
|
||||
0xD5 => 2, // CMP zpx
|
||||
0xCD => 3, // CMP abs
|
||||
0xDD => 3, // CMP abx
|
||||
0xD9 => 3, // CMP aby
|
||||
0xC1 => 2, // CMP izx
|
||||
0xD1 => 2, // CMP izy
|
||||
0xE0 => 2, // CPX imm
|
||||
0xE4 => 2, // CPX zp
|
||||
0xEC => 3, // CPX abs
|
||||
0xC0 => 2, // CPY imm
|
||||
0xC4 => 2, // CPY zp
|
||||
0xCC => 3, // CPY abs
|
||||
_ => 1, // fallback, would show the invalid/unknown opcode only not its parameters
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user