From e1f62408ca43071a936dc5bbdbea68c6e7384c17 Mon Sep 17 00:00:00 2001 From: JakeBreath Date: Sat, 8 Aug 2026 18:31:14 -0500 Subject: [PATCH] implemented all LDx family of instructions --- src/cpu.rs | 102 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 86 insertions(+), 16 deletions(-) diff --git a/src/cpu.rs b/src/cpu.rs index 0842aea..332c503 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -131,6 +131,15 @@ impl Cpu { 0xB9 => self.lda_aby(bus), 0xA1 => self.lda_izx(bus), 0xB1 => self.lda_izy(bus), + 0xA6 => self.ldx_zp(bus), // LDX zp + 0xB6 => self.ldx_zpy(bus), // LDX zpy + 0xAE => self.ldx_abs(bus), // LDX abs + 0xBE => self.ldx_aby(bus), // LDX aby + 0xA0 => self.ldy_imm(bus), // LDY imm + 0xA4 => self.ldy_zp(bus), // LDY zp + 0xB4 => self.ldy_zpx(bus), // LDY zpx + 0xAC => self.ldy_abs(bus), // LDY abs + 0xBC => self.ldy_abx(bus), // LDY abx _ => panic!("illegal/unkown opcode {opcode:#04X} at {:#06X}", self.pc.wrapping_sub(1)), }; self.cycles += cycles as u64; @@ -228,31 +237,30 @@ impl Cpu { cycles } - // shared cores for LDx instructions - fn lda(&mut self,bus: &mut impl Bus, (address, extra): (u16, u8), base: u8) -> u8 { + // Shared cores for LDx instructions + fn lda(&mut self, bus: &mut impl Bus, (address, extra): (u16, u8), base: u8) -> u8 { self.a = self.read(bus, address); self.set_zp_flags(self.a); base + extra } - // 0xA9, LDA immediate instructions: operand is inline, fetch consumes it, no address helper - fn lda_imm(&mut self, bus: &mut impl Bus) -> u8 { - self.a = self.fetch(bus); - self.set_zp_flags(self.a); - 2 - } + fn ldx(&mut self, bus: &mut impl Bus, (address, extra): (u16, u8), base: u8) -> u8 { + self.x = self.read(bus, address); + self.set_zp_flags(self.x); + base + extra + } + + fn ldy(&mut self, bus: &mut impl Bus, (address, extra): (u16, u8), base: u8) -> u8 { + self.y = self.read(bus, address); + self.set_zp_flags(self.y); + 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); 3 - } - - 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, 2 bytes, 3 cycles let (addr, _) = self.address_zp(bus); @@ -355,7 +363,7 @@ impl Cpu { 2 } - // LDA alternatives here + // LDA alternatives fn lda_zp(&mut self, bus: &mut impl Bus) -> u8 { // 0xA5, 2 bytes let (address, extra) = self.address_zp(bus); self.lda(bus, (address, extra), 3) @@ -384,6 +392,59 @@ impl Cpu { let (address, extra) = self.address_izy(bus); self.lda(bus, (address, extra), 5) } + // 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) + } + 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) + } + 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) + } + 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) + } + // 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) + } + 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) + } + 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) + } + 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) + } + + // imm variants + fn lda_imm(&mut self, bus: &mut impl Bus) -> u8 { // 0xA9, 2 bytes, 2 cycles + self.a = self.fetch(bus); + self.set_zp_flags(self.a); + 2 + } + + 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 ldy_imm(&mut self, bus: &mut impl Bus) -> u8 { // 0xA0, 2 bytes, 2 cycles + self.y = self.fetch(bus); + 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 @@ -433,6 +494,15 @@ impl Cpu { 0xB9 => 3, // LDA aby 0xA1 => 2, // LDA izx 0xB1 => 2, // LDA izy + 0xA6 => 2, // LDX zp + 0xB6 => 2, // LDX zpy + 0xAE => 3, // LDX abs + 0xBE => 3, // LDX aby + 0xA0 => 2, // LDY imm + 0xA4 => 2, // LDY zp + 0xB4 => 2, // LDY zpx + 0xAC => 3, // LDY abs + 0xBC => 3, // LDY abx _ => 1, // fallback, would show the invalid/unknown opcode only not its parameters } }