diff --git a/src/r6502/addressing_modes.rs b/src/r6502/addressing_modes.rs index a3d9f5d..b1db480 100644 --- a/src/r6502/addressing_modes.rs +++ b/src/r6502/addressing_modes.rs @@ -199,9 +199,39 @@ impl AddressingModes ModeID::IZX } + + // Indirect Indexed Addressing (IND), Y + // In indirect indexed addressing, the second byte of the instruction points to + // a memory location in page zero. The contents of this memory location are added to + // the contents of the Y register. The result is the low order byte of the effective address. + // The carry from this addition is added to the contents of the next page zero memory + // location, to form the high order byte of the effective address. + // + // Info from: + // https://web.archive.org/web/20221112231348if_/http://archive.6502.org/datasheets/rockwell_r650x_r651x.pdf pub fn IZY(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID { - + // zp_pointer points to a location in zero page + let zp_pointer = bus.read(cpu.pc) as u16; + cpu.pc += 1; + + // The value at zp_pointer is added to the Y register + let zp_value = bus.read(zp_pointer) as u16; + let sum = zp_value + cpu.y as u16; + + // The sum with the carry discarded is the lo byte + let lo_byte = sum & 0x00FF; + + // The carry plus the value at the next zero page address is the hi byte + let zp_next = bus.read(zp_pointer + 1) as u16; + let temp = (sum & 0xFF00) >> 0x08; + let temp2 = temp + zp_next; + let hi_byte: u8 = (((sum & 0xFF00) >> 0x08) + zp_next) as u8; + + // Store the final address and read the data + cpu.working_addr = ((hi_byte as u16) << 0x08) | lo_byte; + cpu.working_data = bus.read(cpu.working_addr) as u16; + ModeID::IZY } } \ No newline at end of file diff --git a/src/tests/instructions/LDA.rs b/src/tests/instructions/LDA.rs index f8a5d56..12c4d5d 100644 --- a/src/tests/instructions/LDA.rs +++ b/src/tests/instructions/LDA.rs @@ -226,6 +226,44 @@ fn IZX() // Clock the cpu to run the program (Clock essentially runs one full instruction) cpu.clock(&mut bus); + // Is 0x08 in the A register? + assert_eq!(0x08, cpu.debug_get_reg(Registers::A)); +} + +#[test] +fn IZY() +{ + let mut cpu = R6502::new(); + let mut bus = RAMBus::new(); + + // program address + let addr = 0x0020 as u16; + + // Set the program counter address + bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte + bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte + + // Manually put 0x08 into memory + bus.write(0x020B, 0x08); + + // Manuall put 0x01FC into the Zero page at 0x000A + // This will be added to the Y register (which will store 0x0F) + bus.write(0x000A, 0xFC); // Pointer lo byte + bus.write(0x000B, 0x01); // Pointer hi byte + + // Program to load 0x08 into the accumulator + bus.write(addr, 0xB1); // LDA - Indirect, Y mode + bus.write(addr + 1, 0x0A); // Argument - Pointer into the Zero Page + + // Restart cpu + cpu.reset(&mut bus); + + // manually setup the cpu registers + cpu.debug_set_reg(Registers::Y, 0x0F); // Offset of the value at the zero page address + + // Clock the cpu to run the program (Clock essentially runs one full instruction) + cpu.clock(&mut bus); + // Is 0x08 in the A register? assert_eq!(0x08, cpu.debug_get_reg(Registers::A)); } \ No newline at end of file