diff --git a/src/r6502/addressing_modes.rs b/src/r6502/addressing_modes.rs index b1db480..8c4dd4c 100644 --- a/src/r6502/addressing_modes.rs +++ b/src/r6502/addressing_modes.rs @@ -7,7 +7,7 @@ use super::{R6502, Bus}; pub enum ModeID { IMP, // Implied - ACM, // Accumulator - Not using, IMP might cover this + ACM, // Accumulator IMM, // Immediate ZP0, // Zero Page ZPX, // Zero Page, X @@ -19,6 +19,7 @@ pub enum ModeID IND, // Indirect IZX, // Indirect, X IZY, // Indirect, Y + ERR, // Error mode - this is an invalid mode } @@ -38,9 +39,11 @@ pub enum ModeID // GROUP TWO ADDRESS MODES // 000 #immediate IMM // 001 zero page ZP0 -// 010 accumulator IMP +// 010 accumulator ACM // 011 absolute ABS +// 100 NONE ERR // 101 zero page,X ZPX +// 110 NONE ERR // 111 absolute,X ABX pub struct AddressingModes; @@ -57,18 +60,37 @@ impl AddressingModes AddressingModes::ABX, ]; - + pub const GROUP_TWO_ADDRS: [fn(&mut R6502, &mut dyn Bus) -> ModeID; 8] = [ + AddressingModes::IMM, + AddressingModes::ZP0, + AddressingModes::ACM, + AddressingModes::ABS, + AddressingModes::ERR, + AddressingModes::ZPX, + AddressingModes::ERR, + AddressingModes::ABX, + ]; } impl AddressingModes { - // This is also the accumulator mode + + pub fn ERR(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID + { + ModeID::ERR + } + pub fn IMP(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID { - cpu.working_data = cpu.a as u16; ModeID::IMP } + pub fn ACM(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID + { + cpu.working_data = cpu.a as u16; + ModeID::ACM + } + pub fn IMM(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID { cpu.working_data = bus.read(cpu.pc) as u16; diff --git a/src/r6502/instructions.rs b/src/r6502/instructions.rs index fa839b6..fb05799 100644 --- a/src/r6502/instructions.rs +++ b/src/r6502/instructions.rs @@ -2,7 +2,7 @@ #![allow(dead_code, non_snake_case)] -use super::{R6502, Bus, Flags}; +use super::{R6502, Bus, Flags, addressing_modes::{AddressingModes, ModeID}}; // Instruction decoding: // https://llx.com/Neil/a2/opcodes.html @@ -22,14 +22,25 @@ pub struct Instructions; impl Instructions { pub const GROUP_ONE_OPS: [fn(&mut R6502, &mut dyn Bus); 8] = [ - Instructions::ORA, - Instructions::AND, - Instructions::EOR, - Instructions::ADC, - Instructions::STA, - Instructions::LDA, - Instructions::CMP, - Instructions::SBC, + Instructions::ORA, + Instructions::AND, + Instructions::EOR, + Instructions::ADC, + Instructions::STA, + Instructions::LDA, + Instructions::CMP, + Instructions::SBC, + ]; + + pub const GROUP_TWO_OPS: [fn(&mut R6502, &mut dyn Bus); 8] = [ + Instructions::ASL, // 000 + Instructions::ROL, // 001 + Instructions::LSR, // 010 + Instructions::ROR, // 011 + Instructions::STX, // 100 + Instructions::LDX, // 101 + Instructions::DEC, // 110 + Instructions::INC, // 111 ]; } @@ -213,6 +224,71 @@ impl Instructions /////////////////////////////////////////////////////////// // GROUP TWO + pub fn ASL(cpu: &mut R6502, bus: &mut dyn Bus) + { + cpu.clear_flag(Flags::C); + if cpu.working_data as u8 & 0x80 > 0 + { + cpu.set_flag(Flags::C); + } + + let result = cpu.working_data << 1; + + cpu.clear_flag(Flags::Z); + if result == 0 + { + cpu.set_flag(Flags::Z); + } + + if result as u8 & 0x80 > 0 + { + cpu.set_flag(Flags::N); + } + + if cpu.addr_mode == ModeID::ACM + { + cpu.a = result as u8; + } + else + { + bus.write(cpu.working_addr, result as u8); + } + } + + pub fn ROL(cpu: &mut R6502, bus: &mut dyn Bus) + { + + } + + pub fn LSR(cpu: &mut R6502, bus: &mut dyn Bus) + { + + } + + pub fn ROR(cpu: &mut R6502, bus: &mut dyn Bus) + { + + } + + pub fn STX(cpu: &mut R6502, bus: &mut dyn Bus) + { + + } + + pub fn LDX(cpu: &mut R6502, bus: &mut dyn Bus) + { + + } + + pub fn DEC(cpu: &mut R6502, bus: &mut dyn Bus) + { + + } + + pub fn INC(cpu: &mut R6502, bus: &mut dyn Bus) + { + + } /////////////////////////////////////////////////////////// // GROUP THREE diff --git a/src/r6502/mod.rs b/src/r6502/mod.rs index bf93083..0ca2471 100644 --- a/src/r6502/mod.rs +++ b/src/r6502/mod.rs @@ -199,6 +199,41 @@ fn exe_group_one(instruction: u8, cpu: &mut R6502, bus: &mut dyn Bus) fn exe_group_two(instruction: u8, cpu: &mut R6502, bus: &mut dyn Bus) { - + let addr_mask = (instruction & 0x1C) >> 2; + let op_mask = (instruction & 0xE0) >> 5; + + // With STX and LDX, "zero page,X" addressing becomes "zero page,Y", and with LDX, "absolute,X" becomes "absolute,Y". + const STX_ZPX: u8 = 0x96; + const LDX_ZPX: u8 = 0xB6; + const LDX_ABX: u8 = 0xBE; + + + match instruction + { + STX_ZPX => + { + cpu.addr_mode = AddressingModes::ZPY(cpu, bus); + Instructions::STX(cpu, bus); + }, + + LDX_ZPX => + { + cpu.addr_mode = AddressingModes::ZPY(cpu, bus); + Instructions::LDX(cpu, bus); + } + + LDX_ABX => + { + + cpu.addr_mode = AddressingModes::ABY(cpu, bus); + Instructions::LDX(cpu, bus); + } + + _ => + { + cpu.addr_mode = AddressingModes::GROUP_TWO_ADDRS[addr_mask as usize](cpu, bus); + Instructions::GROUP_TWO_OPS[op_mask as usize](cpu, bus); + } + } } diff --git a/src/tests/instructions/mod.rs b/src/tests/instructions/mod.rs index 8857328..2d2bb09 100644 --- a/src/tests/instructions/mod.rs +++ b/src/tests/instructions/mod.rs @@ -2,8 +2,11 @@ #![allow(dead_code, non_snake_case)] use crate::tests::test_bus::RAMBus; -use crate::r6502::{R6502, Bus, Registers, Flags}; +use crate::r6502::{R6502, Bus, Registers}; +///////////////////////////////////////////////////////////////////// +// GROUP ONE +///////////////////////////////////////////////////////////////////// #[test] fn ORA() @@ -163,4 +166,10 @@ fn STA() mod CMP; #[cfg(test)] -mod SBC; \ No newline at end of file +mod SBC; + +///////////////////////////////////////////////////////////////////// +// GROUP TWO +///////////////////////////////////////////////////////////////////// + +// TODO: TEST ASL \ No newline at end of file