diff --git a/cli/src/bin/decode.rs b/cli/src/bin/decode.rs index 3bde970..b597f2f 100644 --- a/cli/src/bin/decode.rs +++ b/cli/src/bin/decode.rs @@ -1,11 +1,10 @@ use core::instruction::Instruction; use core::address_mode::AddressMode; -use core::isa::decoder::Decoder; fn main() { println!("Taxation is Theft"); - Decoder::decode(vec![0b11100011]); + Instruction::from_bytes(vec![0b11100011]); let instruction = Instruction::ADC(AddressMode::Immediate(0x45)); println!("Instruction = {:?}", instruction.to_string()); diff --git a/core/Cargo.toml b/core/Cargo.toml index 7fe5433..eb6323e 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -3,4 +3,4 @@ name = "core" version = "0.1.0" edition = "2024" [dependencies] -log = "0.4.26" \ No newline at end of file +log = "0.4" \ No newline at end of file diff --git a/core/src/address_mode.rs b/core/src/address_mode.rs index 0492068..bf86d19 100644 --- a/core/src/address_mode.rs +++ b/core/src/address_mode.rs @@ -1,17 +1,23 @@ +use std::fmt::{Display, Formatter}; use std::ops::Add; +use crate::address_mode::Operation::*; +use crate::constants::constants_isa_op::*; +use crate::constants::constants_isa_stub::*; use crate::mos6502cpu::Mos6502Cpu; +use crate::operation::Operation; -#[derive(PartialEq, Debug)] +#[derive(PartialEq, Debug, Copy, Clone)] pub enum AddressMode { Implied, Accumulator, - Immediate(u8), - ZeroPage(u8), - ZeroPageX(u8), - ZeroPageY(u8), - Absolute(u16), - AbsoluteX(u16), - AbsoluteY(u16), - IndirectX(u8), - IndirectY(u8), + Immediate, + ZeroPage, + ZeroPageX, + ZeroPageY, + Absolute, + AbsoluteX, + AbsoluteY, + Indirect, + IndirectX, + IndirectY, } diff --git a/core/src/constants/constants_isa_op.rs b/core/src/constants/constants_isa_op.rs index d766451..1324ca5 100644 --- a/core/src/constants/constants_isa_op.rs +++ b/core/src/constants/constants_isa_op.rs @@ -57,6 +57,7 @@ pub const ISA_OP_CMP_ZP: u8 = 0xc5; pub const ISA_OP_CMP_ZPX: u8 = 0xd5; pub const ISA_OP_CMP_ABS: u8 = 0xcd; pub const ISA_OP_CMP_ABSX: u8 = 0xdd; +pub const ISA_OP_CMP_ABSY: u8 = 0xd9; pub const ISA_OP_CMP_INDX: u8 = 0xc1; pub const ISA_OP_CMP_INDY: u8 = 0xd1; pub const ISA_OP_CPX_I: u8 = 0xe0; @@ -156,7 +157,7 @@ pub const ISA_OP_STA_ABSY: u8 = 0x99; pub const ISA_OP_STA_INDX: u8 = 0x81; pub const ISA_OP_STA_INDY: u8 = 0x91; pub const ISA_OP_STX_ZP: u8 = 0x86; -pub const ISA_OP_STX_ZPX: u8 = 0x96; +pub const ISA_OP_STX_ZPY: u8 = 0x96; pub const ISA_OP_STX_ABS: u8 = 0x8e; pub const ISA_OP_STY_ZP: u8 = 0x84; pub const ISA_OP_STY_ZPX: u8 = 0x94; diff --git a/core/src/instruction.rs b/core/src/instruction.rs new file mode 100644 index 0000000..fa20365 --- /dev/null +++ b/core/src/instruction.rs @@ -0,0 +1,242 @@ +use crate::address_mode::AddressMode; +use crate::address_mode::AddressMode::*; +use crate::address_mode::AddressMode::{Absolute, AbsoluteX, AbsoluteY, Accumulator, Immediate, Implied, Indirect, IndirectX, IndirectY, ZeroPage, ZeroPageX}; +use crate::instruction_table::INSTRUCTION_TABLE; +use crate::operand::Operand; +use crate::operation::Operation; +use crate::operation::Operation::{ADC, AND, ASL, BCC, BCS, BEQ, BIT, BMI, BNE, BPL, BRK, BVC, BVS, CLC, CLD, CLI, CLV, CMP, CPX, CPY, DEC, DEX, DEY, EOR, INC, INX, JMP, JSR, LDA, LDX, LDY, NOP, ORA, PHA, PHP, PLA, PLP, ROL, ROR, RTI, RTS, SBC, SEC, SED, SEI, STA, STX, STY, TAX, TAY, TSX, TXA, TXS, TYA}; + +#[derive(Debug, PartialEq)] +pub struct Instruction { + pub op: Operation, + pub mode: AddressMode, + pub operand: Operand, +} + +impl Instruction { + pub fn decode(bytes: &[u8]) -> Option { + let opcode = bytes.get(0).copied()?; + let info = INSTRUCTION_TABLE[opcode as usize]?; + + let operand = match info.length { + 2 => Operand::Byte(bytes.get(1).copied()?), + 3 => { + let lo = *bytes.get(1)?; + let hi = *bytes.get(2)?; + Operand::Word(u16::from_le_bytes([lo, hi])) + } + _ => return None, + }; + + Some(Instruction { + op: info.operation, + mode: info.mode, + operand, + }) + } +} + + +#[cfg(test)] +mod test { + use crate::address_mode::AddressMode::*; + use crate::instruction::Instruction; + use crate::operation::Operation::ADC; + use super::*; + + #[test] + fn decode_instruction() { + let params = vec![ + // ADC + (vec![0x69, 0xab], Instruction { op: ADC, mode: Immediate, operand: Operand::Byte(0xab) }), + (vec![0x65, 0xab], Instruction { op: ADC, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0x75, 0xab], Instruction { op: ADC, mode: ZeroPageX, operand: Operand::Byte(0xab) }), + (vec![0x6d, 0xcd, 0xab], Instruction { op: ADC, mode: Absolute, operand: Operand::Word(0xabcd) }), + (vec![0x7d, 0xcd, 0xab], Instruction { op: ADC, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + (vec![0x79, 0xcd, 0xab], Instruction { op: ADC, mode: AbsoluteY, operand: Operand::Word(0xabcd) }), + (vec![0x61, 0xab], Instruction { op: ADC, mode: IndirectX, operand: Operand::Byte(0xab) }), + (vec![0x71, 0xab], Instruction { op: ADC, mode: IndirectY, operand: Operand::Byte(0xab) }), + // AND + (vec![0x29, 0xab], Instruction { op: AND, mode: Immediate, operand: Operand::Byte(0xab) }), + (vec![0x25, 0xab], Instruction { op: AND, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0x35, 0xab], Instruction { op: AND, mode: ZeroPageX, operand: Operand::Byte(0xab) }), + (vec![0x2d, 0xcd, 0xab], Instruction { op: AND, mode: Absolute, operand: Operand::Word(0xabcd) }), + (vec![0x3d, 0xcd, 0xab], Instruction { op: AND, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + (vec![0x39, 0xcd, 0xab], Instruction { op: AND, mode: AbsoluteY, operand: Operand::Word(0xabcd) }), + (vec![0x21, 0xab], Instruction { op: AND, mode: IndirectX, operand: Operand::Byte(0xab) }), + (vec![0x31, 0xab], Instruction { op: AND, mode: IndirectY, operand: Operand::Byte(0xab) }), + // ASL + (vec![0x0a], Instruction { op: ASL, mode: Accumulator, operand: Operand::None }), + (vec![0x06, 0xab], Instruction { op: ASL, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0x16, 0xab], Instruction { op: ASL, mode: ZeroPageX, operand: Operand::Byte(0xab) }), + (vec![0x0e, 0xcd, 0xab], Instruction { op: ASL, mode: Absolute, operand: Operand::Word(0xabcd) }), + (vec![0x1e, 0xcd, 0xab], Instruction { op: ASL, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + // BIT + (vec![0x24, 0xab], Instruction { op: BIT, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0x2c, 0xcd, 0xab], Instruction { op: BIT, mode: Absolute, operand: Operand::Word(0xabcd) }), + // BCC, BCS, BEQ, BMI, BNE, BPL, BVC, BVS + (vec![0x10, 0xab], Instruction { op: BPL, mode: Immediate, operand: Operand::Byte(0xab) }), + (vec![0x30, 0xab], Instruction { op: BMI, mode: Immediate, operand: Operand::Byte(0xab) }), + (vec![0x50, 0xab], Instruction { op: BVC, mode: Immediate, operand: Operand::Byte(0xab) }), + (vec![0x70, 0xab], Instruction { op: BVS, mode: Immediate, operand: Operand::Byte(0xab) }), + (vec![0x90, 0xab], Instruction { op: BCC, mode: Immediate, operand: Operand::Byte(0xab) }), + (vec![0xb0, 0xab], Instruction { op: BCS, mode: Immediate, operand: Operand::Byte(0xab) }), + (vec![0xd0, 0xab], Instruction { op: BNE, mode: Immediate, operand: Operand::Byte(0xab) }), + (vec![0xf0, 0xab], Instruction { op: BEQ, mode: Immediate, operand: Operand::Byte(0xab) }), + // BRK + (vec![0x00], Instruction { op: BRK, mode: Implied, operand: Operand::None }), + // CLC, CLD, CLI, CLV + (vec![0x18], Instruction { op: CLC, mode: Implied, operand: Operand::None }), + (vec![0xd8], Instruction { op: CLD, mode: Implied, operand: Operand::None }), + (vec![0x58], Instruction { op: CLI, mode: Implied, operand: Operand::None }), + (vec![0xb8], Instruction { op: CLV, mode: Implied, operand: Operand::None }), + // CMP + (vec![0xc9, 0xab], Instruction { op: CMP, mode: Immediate, operand: Operand::Byte(0xab) }), + (vec![0xc5, 0xab], Instruction { op: CMP, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0xd5, 0xab], Instruction { op: CMP, mode: ZeroPageX, operand: Operand::Byte(0xab) }), + (vec![0xcd, 0xcd, 0xab], Instruction { op: CMP, mode: Absolute, operand: Operand::Word(0xabcd) }), + (vec![0xdd, 0xcd, 0xab], Instruction { op: CMP, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + (vec![0xd9, 0xcd, 0xab], Instruction { op: CMP, mode: AbsoluteY, operand: Operand::Word(0xabcd) }), + (vec![0xc1, 0xab], Instruction { op: CMP, mode: IndirectX, operand: Operand::Byte(0xab) }), + (vec![0xd1, 0xab], Instruction { op: CMP, mode: IndirectY, operand: Operand::Byte(0xab) }), + // CPX + (vec![0xe0, 0xab], Instruction { op: CPX, mode: Immediate, operand: Operand::Byte(0xab) }), + (vec![0xe4, 0xab], Instruction { op: CPX, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0xec, 0xcd, 0xab], Instruction { op: CPX, mode: Absolute, operand: Operand::Word(0xabcd) }), + // CPY + (vec![0xc0, 0xab], Instruction { op: CPY, mode: Immediate, operand: Operand::Byte(0xab) }), + (vec![0xc4, 0xab], Instruction { op: CPY, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0xcc, 0xcd, 0xab], Instruction { op: CPY, mode: Absolute, operand: Operand::Word(0xabcd) }), + // DEC, DEX, DEY + (vec![0xc6, 0xab], Instruction { op: DEC, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0xd6, 0xab], Instruction { op: DEC, mode: ZeroPageX, operand: Operand::Byte(0xab) }), + (vec![0xce, 0xcd, 0xab], Instruction { op: DEC, mode: Absolute, operand: Operand::Word(0xabcd) }), + (vec![0xde, 0xcd, 0xab], Instruction { op: DEC, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + (vec![0xca], Instruction { op: DEX, mode: Implied, operand: Operand::None }), + (vec![0x88], Instruction { op: DEY, mode: Implied, operand: Operand::None }), + // EOR + (vec![0x49, 0xab], Instruction { op: EOR, mode: Immediate, operand: Operand::Byte(0xab) }), + (vec![0x45, 0xab], Instruction { op: EOR, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0x55, 0xab], Instruction { op: EOR, mode: ZeroPageX, operand: Operand::Byte(0xab) }), + (vec![0x4d, 0xcd, 0xab], Instruction { op: EOR, mode: Absolute, operand: Operand::Word(0xabcd) }), + (vec![0x5d, 0xcd, 0xab], Instruction { op: EOR, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + (vec![0x59, 0xcd, 0xab], Instruction { op: EOR, mode: AbsoluteY, operand: Operand::Word(0xabcd) }), + (vec![0x41, 0xab], Instruction { op: EOR, mode: IndirectX, operand: Operand::Byte(0xab) }), + (vec![0x51, 0xab], Instruction { op: EOR, mode: IndirectY, operand: Operand::Byte(0xab) }), + // INC, INX, INY + (vec![0xe6, 0xab], Instruction { op: INC, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0xf6, 0xab], Instruction { op: INC, mode: ZeroPageX, operand: Operand::Byte(0xab) }), + (vec![0xee, 0xcd, 0xab], Instruction { op: INC, mode: Absolute, operand: Operand::Word(0xabcd) }), + (vec![0xfe, 0xcd, 0xab], Instruction { op: INC, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + (vec![0xe8], Instruction { op: INX, mode: Implied, operand: Operand::None }), + (vec![0xc8], Instruction { op: INX, mode: Implied, operand: Operand::None }), + // JMP, JSR + (vec![0x4c, 0xcd, 0xab], Instruction { op: JMP, mode: Absolute, operand: Operand::Word(0xabcd) }), + (vec![0x6c, 0xcd, 0xab], Instruction { op: JMP, mode: Indirect, operand: Operand::Word(0xabcd) }), + (vec![0x20], Instruction { op: JSR, mode: Implied, operand: Operand::None }), + // LDA + (vec![0xa9, 0xab], Instruction { op: LDA, mode: Immediate, operand: Operand::Byte(0xab) }), + (vec![0xa5, 0xab], Instruction { op: LDA, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0xb5, 0xab], Instruction { op: LDA, mode: ZeroPageX, operand: Operand::Byte(0xab) }), + (vec![0xad, 0xcd, 0xab], Instruction { op: LDA, mode: Absolute, operand: Operand::Word(0xabcd) }), + (vec![0xbd, 0xcd, 0xab], Instruction { op: LDA, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + (vec![0xb9, 0xcd, 0xab], Instruction { op: LDA, mode: AbsoluteY, operand: Operand::Word(0xabcd) }), + (vec![0xa1, 0xab], Instruction { op: LDA, mode: IndirectX, operand: Operand::Byte(0xab) }), + (vec![0xb1, 0xab], Instruction { op: LDA, mode: IndirectY, operand: Operand::Byte(0xab) }), + // LDX + (vec![0xa2, 0xab], Instruction { op: LDX, mode: Immediate, operand: Operand::Byte(0xab) }), + (vec![0xa6, 0xab], Instruction { op: LDX, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0xb6, 0xab], Instruction { op: LDX, mode: ZeroPageX, operand: Operand::Byte(0xab) }), + (vec![0xae, 0xcd, 0xab], Instruction { op: LDX, mode: Absolute, operand: Operand::Word(0xabcd) }), + (vec![0xbe, 0xcd, 0xab], Instruction { op: LDX, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + // LDY + (vec![0xa2, 0xab], Instruction { op: LDY, mode: Immediate, operand: Operand::Byte(0xab) }), + (vec![0xa6, 0xab], Instruction { op: LDY, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0xb6, 0xab], Instruction { op: LDY, mode: ZeroPageX, operand: Operand::Byte(0xab) }), + (vec![0xae, 0xcd, 0xab], Instruction { op: LDY, mode: Absolute, operand: Operand::Word(0xabcd) }), + (vec![0xbe, 0xcd, 0xab], Instruction { op: LDY, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + // LSR + (vec![0x4a, 0xab], Instruction { op: LDY, mode: Accumulator, operand: Operand::Byte(0xab) }), + (vec![0x46, 0xab], Instruction { op: LDY, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0x56, 0xab], Instruction { op: LDY, mode: ZeroPageX, operand: Operand::Byte(0xab) }), + (vec![0x4e, 0xcd, 0xab], Instruction { op: LDY, mode: Absolute, operand: Operand::Word(0xabcd) }), + (vec![0x5e, 0xcd, 0xab], Instruction { op: LDY, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + // NOP + (vec![0xea], Instruction { op: NOP, mode: Implied, operand: Operand::None }), + // ORA + (vec![0x09, 0xab], Instruction { op: ORA, mode: Immediate, operand: Operand::Byte(0xab) }), + (vec![0x05, 0xab], Instruction { op: ORA, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0x15, 0xab], Instruction { op: ORA, mode: ZeroPageX, operand: Operand::Byte(0xab) }), + (vec![0x0d, 0xcd, 0xab], Instruction { op: ORA, mode: Absolute, operand: Operand::Word(0xabcd) }), + (vec![0x1d, 0xcd, 0xab], Instruction { op: ORA, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + (vec![0x19, 0xcd, 0xab], Instruction { op: ORA, mode: AbsoluteY, operand: Operand::Word(0xabcd) }), + (vec![0x01, 0xab], Instruction { op: ORA, mode: IndirectX, operand: Operand::Byte(0xab) }), + (vec![0x11, 0xab], Instruction { op: ORA, mode: IndirectY, operand: Operand::Byte(0xab) }), + // PHA, PHP, PLA, PLP + (vec![0x48], Instruction { op: PHA, mode: Implied, operand: Operand::None }), + (vec![0x08], Instruction { op: PHP, mode: Implied, operand: Operand::None }), + (vec![0x68], Instruction { op: PLA, mode: Implied, operand: Operand::None }), + (vec![0x28], Instruction { op: PLP, mode: Implied, operand: Operand::None }), + // ROL + (vec![0x2a, 0xab], Instruction { op: ROL, mode: Accumulator, operand: Operand::Byte(0xab) }), + (vec![0x26, 0xab], Instruction { op: ROL, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0x36, 0xab], Instruction { op: ROL, mode: ZeroPageX, operand: Operand::Byte(0xab) }), + (vec![0x2e, 0xcd, 0xab], Instruction { op: ROL, mode: Absolute, operand: Operand::Word(0xabcd) }), + (vec![0x3e, 0xcd, 0xab], Instruction { op: ROL, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + // ROR + (vec![0x6a, 0xab], Instruction { op: ROR, mode: Accumulator, operand: Operand::Byte(0xab) }), + (vec![0x66, 0xab], Instruction { op: ROR, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0x76, 0xab], Instruction { op: ROR, mode: ZeroPageX, operand: Operand::Byte(0xab) }), + (vec![0x6e, 0xcd, 0xab], Instruction { op: ROR, mode: Absolute, operand: Operand::Word(0xabcd) }), + (vec![0x7e, 0xcd, 0xab], Instruction { op: ROR, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + // RTI, RTS + (vec![0x40], Instruction { op: RTI, mode: Implied, operand: Operand::None }), + (vec![0x60], Instruction { op: RTS, mode: Implied, operand: Operand::None }), + // SBC + (vec![0xe9, 0xab], Instruction { op: SBC, mode: Immediate, operand: Operand::Byte(0xab) }), + (vec![0xe5, 0xab], Instruction { op: SBC, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0xf5, 0xab], Instruction { op: SBC, mode: ZeroPageX, operand: Operand::Byte(0xab) }), + (vec![0xed, 0xcd, 0xab], Instruction { op: SBC, mode: Absolute, operand: Operand::Word(0xabcd) }), + (vec![0xfd, 0xcd, 0xab], Instruction { op: SBC, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + (vec![0xf9, 0xcd, 0xab], Instruction { op: SBC, mode: AbsoluteY, operand: Operand::Word(0xabcd) }), + (vec![0xe1, 0xab], Instruction { op: SBC, mode: IndirectX, operand: Operand::Byte(0xab) }), + (vec![0xf1, 0xab], Instruction { op: SBC, mode: IndirectY, operand: Operand::Byte(0xab) }), + // SEC, SED, SEI + (vec![0x38], Instruction { op: SEC, mode: Implied, operand: Operand::None }), + (vec![0xf8], Instruction { op: SED, mode: Implied, operand: Operand::None }), + (vec![0x78], Instruction { op: SEI, mode: Implied, operand: Operand::None }), + // STA + (vec![0x85, 0xab], Instruction { op: STA, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0x95, 0xab], Instruction { op: STA, mode: ZeroPageX, operand: Operand::Byte(0xab) }), + (vec![0x8d, 0xcd, 0xab], Instruction { op: STA, mode: Absolute, operand: Operand::Word(0xabcd) }), + (vec![0x9d, 0xcd, 0xab], Instruction { op: STA, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), + (vec![0x99, 0xcd, 0xab], Instruction { op: STA, mode: AbsoluteY, operand: Operand::Word(0xabcd) }), + (vec![0x81, 0xab], Instruction { op: STA, mode: IndirectX, operand: Operand::Byte(0xab) }), + (vec![0x91, 0xab], Instruction { op: STA, mode: IndirectY, operand: Operand::Byte(0xab) }), + // STX + (vec![0x86, 0xab], Instruction { op: STX, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0x96, 0xab], Instruction { op: STX, mode: ZeroPageX, operand: Operand::Byte(0xab) }), + (vec![0x8e, 0xcd, 0xab], Instruction { op: STX, mode: Absolute, operand: Operand::Word(0xabcd) }), + // STY + (vec![0x84, 0xab], Instruction { op: STY, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0x94, 0xab], Instruction { op: STY, mode: ZeroPageX, operand: Operand::Byte(0xab) }), + (vec![0x8c, 0xcd, 0xab], Instruction { op: STY, mode: Absolute, operand: Operand::Word(0xabcd) }), + // TAX, TAY, TSX, TXA, TXS, TYA + (vec![0xaa], Instruction { op: TAX, mode: Implied, operand: Operand::None }), + (vec![0xa8], Instruction { op: TAY, mode: Implied, operand: Operand::None }), + (vec![0xba], Instruction { op: TSX, mode: Implied, operand: Operand::None }), + (vec![0x8a], Instruction { op: TXA, mode: Implied, operand: Operand::None }), + (vec![0x9a], Instruction { op: TXS, mode: Implied, operand: Operand::None }), + (vec![0x98], Instruction { op: TYA, mode: Implied, operand: Operand::None }) + ]; + for (bytes, instruction) in params { + let result = Instruction::decode(&bytes); + if let Some(instruction) = result { + assert_eq!(Instruction::decode(&bytes).unwrap(), instruction) + } else { + println!("Failed to decode {:?}", bytes); + } + + } + } +} \ No newline at end of file diff --git a/core/src/instruction/execute.rs b/core/src/instruction/execute.rs deleted file mode 100644 index 825f225..0000000 --- a/core/src/instruction/execute.rs +++ /dev/null @@ -1,285 +0,0 @@ -use log::debug; -use crate::address_mode::AddressMode; -use crate::instruction::Instruction; -use crate::mos6502cpu::Mos6502Cpu; -use crate::mos6502flags::Mos6502Flag::{Carry, Decimal, Interrupt, Overflow}; - -impl Instruction { - fn execute(&self, mut system: Mos6502Cpu) { - match self { - // ADC – Add with Carry - // A,Z,C,N = A+M+C - // - // This instruction adds the contents of a memory location to the accumulator together with the carry bit. If overflow occurs the carry bit is set, this enables multiple byte addition to be performed. - // - // Processor Status after use: - // - // C Carry Flag Set if overflow in bit 7 - // Z Zero Flag Set if A = 0 - // I Interrupt Disable Not affected - // D Decimal Mode Flag Not affected - // B Break Command Not affected - // V Overflow Flag Set if sign bit is incorrect - // N Negative Flag Set if bit 7 set - Instruction::ADC(mode) => { - match mode { - AddressMode::Immediate(_) => {} - AddressMode::ZeroPage(_) => {} - AddressMode::ZeroPageX(_) => {} - AddressMode::Absolute(_) => {} - AddressMode::AbsoluteX(_) => {} - AddressMode::AbsoluteY(_) => {} - AddressMode::IndirectX(_) => {} - AddressMode::IndirectY(_) => {} - _ => {} - } - } - Instruction::AND(address) => { - match address { - AddressMode::Immediate(_) => {} - AddressMode::ZeroPage(_) => {} - AddressMode::ZeroPageX(_) => {} - AddressMode::Absolute(_) => {} - AddressMode::AbsoluteX(_) => {} - AddressMode::AbsoluteY(_) => {} - AddressMode::IndirectX(_) => {} - AddressMode::IndirectY(_) => {} - _ => { - // NOOP - } - } - } - Instruction::ASL(mode) => { - match mode { - // ISA_OP_ASL_A - AddressMode::Accumulator => {} - AddressMode::ZeroPage(_) => {} - AddressMode::ZeroPageX(_) => {} - AddressMode::Absolute(_) => {} - AddressMode::AbsoluteX(_) => {} - _ => {} - } - } - Instruction::BCC(mode) => { - match mode { - AddressMode::Immediate(value) => {} - _ => {} - } - } - Instruction::BCS(mode) => { - match mode { - AddressMode::Immediate(value) => {} - _ => {} - } - } - Instruction::BEQ(mode) => { - match mode { - AddressMode::Immediate(value) => {} - _ => {} - } - } - Instruction::BIT(mode) => { - match mode { - AddressMode::ZeroPage(value) => {} - AddressMode::Absolute(value) => {} - _ => {} - } - } - Instruction::BMI(mode) => { - match mode { - AddressMode::Immediate(value) => {} - _ => {} - } - } - Instruction::BNE(mode) => { - match mode { - AddressMode::Immediate(value) => {} - _ => {} - } - } - Instruction::BPL(mode) => { - match mode { - AddressMode::Immediate(value) => {} - _ => {} - } - } - Instruction::BRK => {} - Instruction::BVC(mode) => { - match mode { - AddressMode::Immediate(value) => {} - _ => {} - } - } - Instruction::BVS(mode) => { - match mode { - AddressMode::Immediate(value) => {} - _ => {} - } - } - Instruction::CLC => { - system.poke_flag(Carry, false) - } - Instruction::CLD => { - system.poke_flag(Decimal, false) - } - Instruction::CLI => { - system.poke_flag(Interrupt, false) - } - Instruction::CLV => { - system.poke_flag(Overflow, false) - } - Instruction::CMP(mode) => { - match mode { - AddressMode::Immediate(_) => {} - AddressMode::ZeroPage(_) => {} - AddressMode::ZeroPageX(_) => {} - AddressMode::Absolute(_) => {} - AddressMode::AbsoluteX(_) => {} - AddressMode::AbsoluteY(_) => {} - AddressMode::IndirectX(_) => {} - AddressMode::IndirectY(_) => {} - _ => {} - } - } - Instruction::CPX(mode) => { - match mode { - AddressMode::Immediate(_) => {} - AddressMode::ZeroPage(_) => {} - AddressMode::ZeroPageX(_) => {} - AddressMode::Absolute(_) => {} - AddressMode::AbsoluteX(_) => {} - AddressMode::AbsoluteY(_) => {} - AddressMode::IndirectX(_) => {} - AddressMode::IndirectY(_) => {} - _ => {} - } - } - Instruction::CPY(mode) => { - match mode { - AddressMode::Immediate(_) => {} - AddressMode::ZeroPage(_) => {} - AddressMode::ZeroPageX(_) => {} - AddressMode::Absolute(_) => {} - AddressMode::AbsoluteX(_) => {} - AddressMode::AbsoluteY(_) => {} - AddressMode::IndirectX(_) => {} - AddressMode::IndirectY(_) => {} - _ => {} - } - } - Instruction::DEC(mode) => { - match mode { - AddressMode::ZeroPage(_) => {} - AddressMode::ZeroPageX(_) => {} - AddressMode::Absolute(_) => {} - AddressMode::AbsoluteX(_) => {} - _ => {} - } - } - Instruction::DEX => { - let mut x = system.peek_x(); - x -= 1; - system.poke_x(x); - } - Instruction::DEY => { - let mut y = system.peek_y(); - y -= 1; - system.poke_y(y); - } - Instruction::EOR(mode) => { - match mode { - AddressMode::Immediate(_) => {} - AddressMode::ZeroPage(_) => {} - AddressMode::ZeroPageX(_) => {} - AddressMode::Absolute(_) => {} - AddressMode::AbsoluteX(_) => {} - AddressMode::AbsoluteY(_) => {} - AddressMode::IndirectX(_) => {} - AddressMode::IndirectY(_) => {} - _ => {} - } - } - Instruction::INC(mode) => { - match mode { - AddressMode::ZeroPage(value) => {} - AddressMode::ZeroPageX(value) => {} - AddressMode::Absolute(value) => {} - AddressMode::AbsoluteX(value) => {} - _ => {} - } - } - Instruction::INX => { - let mut x = system.peek_x(); - x += 1; - system.poke_x(x); - } - Instruction::INY => { - let mut y = system.peek_y(); - y += 1; - system.poke_y(y); - } - Instruction::JMP(mode) => { - match mode { - AddressMode::Absolute(_) => {} - AddressMode::IndirectX(_) => {} - _ => {} - } - } - Instruction::JSR(mode) => { - match mode { - AddressMode::Absolute(address) => {} - _ => {} - } - } - Instruction::LDA(mode) => { - match mode { - AddressMode::Immediate(value) => { - system.poke_a(*value) - } - AddressMode::ZeroPage(offset) => { - let value_to_write = system.peek(*offset as u16); - system.poke_a(value_to_write); - } - AddressMode::ZeroPageX(_) => { - let current_x = system.peek_x(); - } - AddressMode::Absolute(_) => {} - AddressMode::AbsoluteX(_) => {} - AddressMode::AbsoluteY(_) => {} - AddressMode::IndirectX(_) => {} - AddressMode::IndirectY(_) => {} - _ => { - debug!("Invalid LDA instruction"); - } - }; - } - Instruction::LDX(_) => {} - Instruction::LDY(_) => {} - Instruction::LSR(_) => {} - Instruction::NOP => {} - Instruction::ORA(_) => {} - Instruction::PHA => {} - Instruction::PHP => {} - Instruction::PLA => {} - Instruction::PLP => {} - Instruction::ROL(_) => {} - Instruction::ROR(_) => {} - Instruction::RTI => {} - Instruction::RTS => {} - Instruction::SBC(_) => {} - Instruction::SEC => {} - Instruction::SED => {} - Instruction::SEI => {} - Instruction::STA(_) => {} - Instruction::STX(_) => {} - Instruction::STY(_) => {} - Instruction::TAX => {} - Instruction::TAY => {} - Instruction::TSX => {} - Instruction::TXA => {} - Instruction::TXS => {} - Instruction::TYA => {} - }; - } - -} \ No newline at end of file diff --git a/core/src/instruction/from_bytes.rs b/core/src/instruction/from_bytes.rs deleted file mode 100644 index 33ae303..0000000 --- a/core/src/instruction/from_bytes.rs +++ /dev/null @@ -1,183 +0,0 @@ -use crate::address_mode::AddressMode::*; -use crate::constants::constants_isa_op::*; -use crate::instruction::Instruction; -use crate::instruction::Instruction::*; - -fn join_word(low: u8, high: u8) -> u16 { - ((high as u16) << 8) | low as u16 -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_join_word() { - let low: u8 = 0xcd; - let high: u8 = 0xab; - - assert_eq!( - join_word(low, high), - 0xabcd - ); - } -} - -impl Instruction { - pub fn from_bytes(decode_from: Vec) -> Instruction { - let id_byte = decode_from[0]; - match id_byte { - ISA_OP_ADC_I..=ISA_OP_ADC_I => ADC(Immediate(decode_from[1])), - ISA_OP_ADC_Z..=ISA_OP_ADC_Z => ADC(ZeroPage(decode_from[1])), - ISA_OP_ADC_ZX..=ISA_OP_ADC_ZX => ADC(ZeroPageX(decode_from[1])), - ISA_OP_ADC_ABS..=ISA_OP_ADC_ABS => ADC(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_ADC_ABSX..=ISA_OP_ADC_ABSX => ADC(AbsoluteX(join_word(decode_from[1], decode_from[2]))), - ISA_OP_ADC_ABSY..=ISA_OP_ADC_ABSY => ADC(AbsoluteY(join_word(decode_from[1], decode_from[2]))), - ISA_OP_ADC_INDX..=ISA_OP_ADC_INDX => ADC(IndirectX(decode_from[1])), - ISA_OP_ADC_INDY..=ISA_OP_ADC_INDY => ADC(IndirectY(decode_from[1])), - ISA_OP_AND_I..=ISA_OP_AND_I => AND(Immediate(decode_from[1])), - ISA_OP_AND_Z..=ISA_OP_AND_Z => AND(ZeroPage(decode_from[1])), - ISA_OP_AND_ZX..=ISA_OP_AND_ZX => AND(ZeroPageX(decode_from[1])), - ISA_OP_AND_ABS..=ISA_OP_AND_ABS => AND(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_AND_ABSX..=ISA_OP_AND_ABSX => AND(AbsoluteX(join_word(decode_from[1], decode_from[2]))), - ISA_OP_AND_ABSY..=ISA_OP_AND_ABSY => AND(AbsoluteY(join_word(decode_from[1], decode_from[2]))), - ISA_OP_AND_INDX..=ISA_OP_AND_INDX => AND(IndirectX(decode_from[1])), - ISA_OP_AND_INDY..=ISA_OP_AND_INDY => AND(IndirectY(decode_from[1])), - ISA_OP_ASL_A..=ISA_OP_ASL_A => ASL(Accumulator), - ISA_OP_ASL_Z..=ISA_OP_ASL_Z => ASL(ZeroPage(decode_from[1])), - ISA_OP_ASL_ZX..=ISA_OP_ASL_ZX => ASL(ZeroPageX(decode_from[1])), - ISA_OP_ASL_ABS..=ISA_OP_ASL_ABS => ASL(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_ASL_ABSX..=ISA_OP_ASL_ABSX => ASL(AbsoluteX(join_word(decode_from[1], decode_from[2]))), - ISA_OP_BCC..=ISA_OP_BCC => BCC(Immediate(decode_from[1])), - ISA_OP_BCS..=ISA_OP_BCS => BCS(Immediate(decode_from[1])), - ISA_OP_BEQ..=ISA_OP_BEQ => BEQ(Immediate(decode_from[1])), - ISA_OP_BIT_ZP..=ISA_OP_BIT_ZP => BIT(ZeroPage(decode_from[1])), - ISA_OP_BIT_ABS..=ISA_OP_BIT_ABS => BIT(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_BMI..=ISA_OP_BMI => BMI(Immediate(decode_from[1])), - ISA_OP_BNE..=ISA_OP_BNE => BNE(Immediate(decode_from[1])), - ISA_OP_BPL..=ISA_OP_BPL => BPL(Immediate(decode_from[1])), - ISA_OP_BRK..=ISA_OP_BRK => BRK, - ISA_OP_BVC..=ISA_OP_BVC => BVC(Immediate(decode_from[1])), - ISA_OP_BVS..=ISA_OP_BVS => BVS(Immediate(decode_from[1])), - ISA_OP_CLC..=ISA_OP_CLC => CLC, - ISA_OP_CLD..=ISA_OP_CLD => CLD, - ISA_OP_CLI..=ISA_OP_CLI => CLI, - ISA_OP_CLV..=ISA_OP_CLV => CLV, - ISA_OP_CMP_I..=ISA_OP_CMP_I => CMP(Immediate(decode_from[1])), - ISA_OP_CMP_ZP..=ISA_OP_CMP_ZP => CMP(ZeroPage(decode_from[1])), - ISA_OP_CMP_ZPX..=ISA_OP_CMP_ZPX => CMP(ZeroPageX(decode_from[1])), - ISA_OP_CMP_ABS..=ISA_OP_CMP_ABS => CMP(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_CMP_ABSX..=ISA_OP_CMP_ABSX => CMP(AbsoluteX(join_word(decode_from[1], decode_from[2]))), - ISA_OP_CMP_INDX..=ISA_OP_CMP_INDX => CMP(IndirectX(decode_from[1])), - ISA_OP_CMP_INDY..=ISA_OP_CMP_INDY => CMP(IndirectY(decode_from[1])), - ISA_OP_CPX_I..=ISA_OP_CPX_I => CPX(Immediate(decode_from[1])), - ISA_OP_CPX_ZP..=ISA_OP_CPX_ZP => CPX(ZeroPage(decode_from[1])), - ISA_OP_CPX_ABS..=ISA_OP_CPX_ABS => CPX(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_CPY_I..=ISA_OP_CPY_I => CPY(Immediate(decode_from[1])), - ISA_OP_CPY_ZP..=ISA_OP_CPY_ZP => CPY(ZeroPage(decode_from[1])), - ISA_OP_CPY_ABS..=ISA_OP_CPY_ABS => CPY(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_DEC_ZP..=ISA_OP_DEC_ZP => DEC(ZeroPage(decode_from[1])), - ISA_OP_DEC_ZPX..=ISA_OP_DEC_ZPX => DEC(ZeroPageX(decode_from[1])), - ISA_OP_DEC_ABS..=ISA_OP_DEC_ABS => DEC(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_DEC_ABSX..=ISA_OP_DEC_ABSX => DEC(AbsoluteX(join_word(decode_from[1], decode_from[1]))), - ISA_OP_DEX..=ISA_OP_DEX => DEX, - ISA_OP_DEY..=ISA_OP_DEY => DEY, - ISA_OP_EOR_I..=ISA_OP_EOR_I => EOR(Immediate(decode_from[1])), - ISA_OP_EOR_ZP..=ISA_OP_EOR_ZP => EOR(ZeroPage(decode_from[1])), - ISA_OP_EOR_ZPX..=ISA_OP_EOR_ZPX => EOR(ZeroPageX(decode_from[1])), - ISA_OP_EOR_ABS..=ISA_OP_EOR_ABS => EOR(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_EOR_ABSX..=ISA_OP_EOR_ABSX => EOR(AbsoluteX(join_word(decode_from[1], decode_from[2]))), - ISA_OP_EOR_ABSY..=ISA_OP_EOR_ABSY => EOR(AbsoluteY(join_word(decode_from[1], decode_from[2]))), - ISA_OP_EOR_INDX..=ISA_OP_EOR_INDX => EOR(IndirectX(decode_from[1])), - ISA_OP_EOR_INDY..=ISA_OP_EOR_INDY => EOR(IndirectY(decode_from[1])), - ISA_OP_INC_ZP..=ISA_OP_INC_ZP => INC(ZeroPage(decode_from[1])), - ISA_OP_INC_ZPX..=ISA_OP_INC_ZPX => INC(ZeroPageX(decode_from[1])), - ISA_OP_INC_ABS..=ISA_OP_INC_ABS => INC(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_INC_ABSX..=ISA_OP_INC_ABSX => INC(AbsoluteX(join_word(decode_from[1], decode_from[2]))), - ISA_OP_INX..=ISA_OP_INX => INX, - ISA_OP_INY..=ISA_OP_INY => INY, - ISA_OP_JMP_ABS..=ISA_OP_JMP_ABS => JMP(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_JMP_IND..=ISA_OP_JMP_IND => JMP(IndirectX(decode_from[1])), - ISA_OP_JSR..=ISA_OP_JSR => JSR(Immediate(decode_from[1])), - ISA_OP_LDA_I..=ISA_OP_LDA_I => LDA(Immediate(decode_from[1])), - ISA_OP_LDA_Z..=ISA_OP_LDA_Z => LDA(ZeroPage(decode_from[1])), - ISA_OP_LDA_ZX..=ISA_OP_LDA_ZX => LDA(ZeroPageX(decode_from[1])), - ISA_OP_LDA_ABS..=ISA_OP_LDA_ABS => LDA(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_LDA_ABSX..=ISA_OP_LDA_ABSX => LDA(AbsoluteX(join_word(decode_from[1], decode_from[2]))), - ISA_OP_LDA_ABSY..=ISA_OP_LDA_ABSY => LDA(AbsoluteY(join_word(decode_from[1], decode_from[2]))), - ISA_OP_LDA_INDX..=ISA_OP_LDA_INDX => LDA(IndirectX(decode_from[1])), - ISA_OP_LDA_INDY..=ISA_OP_LDA_INDY => LDA(IndirectY(decode_from[1])), - ISA_OP_LDX_I..=ISA_OP_LDX_I => LDX(Immediate(decode_from[1])), - ISA_OP_LDX_ZP..=ISA_OP_LDX_ZP => LDX(ZeroPage(decode_from[1])), - ISA_OP_LDX_ZPY..=ISA_OP_LDX_ZPY => LDX(ZeroPageY(decode_from[1])), - ISA_OP_STX_ZP..=ISA_OP_STX_ZP => STX(ZeroPage(decode_from[1])), - ISA_OP_LDX_ABS..=ISA_OP_LDX_ABS => LDX(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_LDX_ABSY..=ISA_OP_LDX_ABSY => LDX(AbsoluteY(join_word(decode_from[1], decode_from[2]))), - ISA_OP_LDY_I..=ISA_OP_LDY_I => LDY(Immediate(decode_from[1])), - ISA_OP_LDY_ZP..=ISA_OP_LDY_ZP => LDY(ZeroPage(decode_from[1])), - ISA_OP_LDY_ZPX..=ISA_OP_LDY_ZPX => LDY(ZeroPageX(decode_from[1])), - ISA_OP_LDY_ABS..=ISA_OP_LDY_ABS => LDY(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_LDY_ABSX..=ISA_OP_LDY_ABSX => LDY(AbsoluteX(join_word(decode_from[1], decode_from[2]))), - ISA_OP_LSR_A..=ISA_OP_LSR_A => LSR(Accumulator), - ISA_OP_LSR_ZP..=ISA_OP_LSR_ZP => LSR(ZeroPage(decode_from[1])), - ISA_OP_LSR_ZPX..=ISA_OP_LSR_ZPX => LSR(ZeroPageX(decode_from[1])), - ISA_OP_LSR_ABS..=ISA_OP_LSR_ABS => LSR(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_LSR_ABSX..=ISA_OP_LSR_ABSX => LSR(AbsoluteX(join_word(decode_from[1], decode_from[2]))), - ISA_OP_NOP..=ISA_OP_NOP => NOP, - ISA_OP_ORA_I..=ISA_OP_ORA_I => ORA(Immediate(decode_from[1])), - ISA_OP_ORA_ZP..=ISA_OP_ORA_ZP => ORA(ZeroPage(decode_from[1])), - ISA_OP_ORA_ZPX..=ISA_OP_ORA_ZPX => ORA(ZeroPageX(decode_from[1])), - ISA_OP_ORA_ABS..=ISA_OP_ORA_ABS => ORA(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_ORA_ABSX..=ISA_OP_ORA_ABSX => ORA(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_ORA_ABSY..=ISA_OP_ORA_ABSY => ORA(AbsoluteY(join_word(decode_from[1], decode_from[2]))), - ISA_OP_ORA_INDX..=ISA_OP_ORA_INDX => ORA(IndirectX(decode_from[1])), - ISA_OP_ORA_INDY..=ISA_OP_ORA_INDY => ORA(IndirectY(decode_from[1])), - ISA_OP_PHA..=ISA_OP_PHA => PHA, - ISA_OP_PHP..=ISA_OP_PHP => PHP, - ISA_OP_PLA..=ISA_OP_PLA => PLA, - ISA_OP_PLP..=ISA_OP_PLP => PLP, - ISA_OP_ROL_A..=ISA_OP_ROL_A => ROL(Accumulator), - ISA_OP_ROL_ZP..=ISA_OP_ROL_ZP => ROL(ZeroPage(decode_from[1])), - ISA_OP_ROL_ZPX..=ISA_OP_ROL_ZPX => ROL(ZeroPageX(decode_from[1])), - ISA_OP_ROL_ABS..=ISA_OP_ROL_ABS => ROL(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_ROL_ABSX..=ISA_OP_ROL_ABSX => ROL(AbsoluteX(join_word(decode_from[1], decode_from[2]))), - ISA_OP_ROR_A..=ISA_OP_ROR_A => ROR(Accumulator), - ISA_OP_ROR_ZP..=ISA_OP_ROR_ZP => ROR(ZeroPage(decode_from[1])), - ISA_OP_ROR_ZPX..=ISA_OP_ROR_ZPX => ROR(ZeroPageX(decode_from[1])), - ISA_OP_ROR_ABS..=ISA_OP_ROR_ABS => ROR(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_ROR_ABSX..=ISA_OP_ROR_ABSX => ROR(AbsoluteX(join_word(decode_from[1], decode_from[2]))), - ISA_OP_RTI..=ISA_OP_RTI => RTI, - ISA_OP_RTS..=ISA_OP_RTS => RTS, - ISA_OP_SBC_I..=ISA_OP_SBC_I => SBC(Immediate(decode_from[1])), - ISA_OP_SBC_ZP..=ISA_OP_SBC_ZP => SBC(ZeroPage(decode_from[1])), - ISA_OP_SBC_ZPX..=ISA_OP_SBC_ZPX => SBC(ZeroPageX(decode_from[1])), - ISA_OP_SBC_ABS..=ISA_OP_SBC_ABS => SBC(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_SBC_ABSX..=ISA_OP_SBC_ABSX => SBC(AbsoluteX(join_word(decode_from[1], decode_from[2]))), - ISA_OP_SBC_ABSY..=ISA_OP_SBC_ABSY => SBC(AbsoluteY(join_word(decode_from[1], decode_from[2]))), - ISA_OP_SBC_INDX..=ISA_OP_SBC_INDX => SBC(IndirectX(decode_from[1])), - ISA_OP_SBC_INDY..=ISA_OP_SBC_INDY => SBC(IndirectY(decode_from[1])), - ISA_OP_SEC..=ISA_OP_SEC => SEC, - ISA_OP_SED..=ISA_OP_SED => SED, - ISA_OP_SEI..=ISA_OP_SEI => SEI, - // ISA_OP_STA_ZP..=ISA_OP_STA_ZP => STA(ZeroPage(decode_from[1])), - ISA_OP_STA_ZPX..=ISA_OP_STA_ZPX => STA(ZeroPageX(decode_from[1])), - ISA_OP_STA_ABS..=ISA_OP_STA_ABS => STA(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_STA_ABSX..=ISA_OP_STA_ABSX => STA(AbsoluteX(join_word(decode_from[1], decode_from[2]))), - ISA_OP_STA_ABSY..=ISA_OP_STA_ABSY => STA(AbsoluteY(join_word(decode_from[1], decode_from[2]))), - ISA_OP_STA_INDX..=ISA_OP_STA_INDX => STA(IndirectX(decode_from[1])), - ISA_OP_STA_INDY..=ISA_OP_STA_INDY => STA(IndirectY(decode_from[1])), - ISA_OP_STX_ZPX..=ISA_OP_STX_ZPX => STX(ZeroPageX(decode_from[1])), - ISA_OP_STX_ABS..=ISA_OP_STX_ABS => STX(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_STY_ZP..=ISA_OP_STY_ZP => STY(ZeroPage(decode_from[1])), - ISA_OP_STY_ZPX..=ISA_OP_STY_ZPX => STY(ZeroPageX(decode_from[1])), - ISA_OP_STY_ABS..=ISA_OP_STY_ABS => STY(Absolute(join_word(decode_from[1], decode_from[2]))), - ISA_OP_TAX..=ISA_OP_TAX => TAX, - ISA_OP_TAY..=ISA_OP_TAY => TAY, - ISA_OP_TSX..=ISA_OP_TSX => TSX, - ISA_OP_TXA..=ISA_OP_TXA => TXA, - ISA_OP_TXS..=ISA_OP_TXS => TXS, - ISA_OP_TYA..=ISA_OP_TYA => TYA, - _ => NOP - } - } -} \ No newline at end of file diff --git a/core/src/instruction/stub.rs b/core/src/instruction/stub.rs deleted file mode 100644 index d2ee3fe..0000000 --- a/core/src/instruction/stub.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crate::instruction::Instruction; -use crate::constants::constants_isa_stub::*; -use crate::instruction::Instruction::*; - -impl Instruction { - /// returns the 'stub' of the instruction. - /// - /// ex: LDA $4452 -> LDA - /// BCC $43 -> BCC - pub fn stub(&self) -> String { - match self { - ADC(_) => ISA_STUB_ADC, - AND(_) => ISA_STUB_AND, - ASL(_) => ISA_STUB_ASL, - BCC(_) => ISA_STUB_BCC, - BCS(_) => ISA_STUB_BCS, - BEQ(_) => ISA_STUB_BEQ, - BIT(_) => ISA_STUB_BIT, - BMI(_) => ISA_STUB_BMI, - BNE(_) => ISA_STUB_BNE, - BPL(_) => ISA_STUB_BPL, - BRK => ISA_STUB_BRK, - BVC(_) => ISA_STUB_BVC, - BVS(_) => ISA_STUB_BVS, - CLC => ISA_STUB_CLC, - CLD => ISA_STUB_CLD, - CLI => ISA_STUB_CLI, - CLV => ISA_STUB_CLV, - CMP(_) => ISA_STUB_CMP, - CPX(_) => ISA_STUB_CPX, - CPY(_) => ISA_STUB_CPY, - DEC(_) => ISA_STUB_DEC, - DEX => ISA_STUB_DEX, - DEY => ISA_STUB_DEY, - EOR(_) => ISA_STUB_EOR, - INC(_) => ISA_STUB_INC, - INX => ISA_STUB_INX, - INY => ISA_STUB_INY, - JMP(_) => ISA_STUB_JMP, - JSR(_) => ISA_STUB_JSR, - LDA(_) => ISA_STUB_LDA, - LDX(_) => ISA_STUB_LDX, - LDY(_) => ISA_STUB_LDY, - LSR(_) => ISA_STUB_LSR, - NOP => ISA_STUB_NOP, - ORA(_) => ISA_STUB_ORA, - PHA => ISA_STUB_PHA, - PHP => ISA_STUB_PHP, - PLA => ISA_STUB_PLA, - PLP => ISA_STUB_PLP, - ROL(_) => ISA_STUB_ROL, - ROR(_) => ISA_STUB_ROR, - RTI => ISA_STUB_RTI, - RTS => ISA_STUB_RTS, - SBC(_) => ISA_STUB_SBC, - SEC => ISA_STUB_SEC, - SED => ISA_STUB_SED, - SEI => ISA_STUB_SEI, - STA(_) => ISA_STUB_STA, - STX(_) => ISA_STUB_STX, - STY(_) => ISA_STUB_STY, - TAX => ISA_STUB_TAX, - TAY => ISA_STUB_TAY, - TSX => ISA_STUB_TSX, - TXA => ISA_STUB_TXA, - TXS => ISA_STUB_TXS, - TYA => ISA_STUB_TYA - }.to_string() - } - -} \ No newline at end of file diff --git a/core/src/instruction/to_bytes.rs b/core/src/instruction/to_bytes.rs deleted file mode 100644 index 6d636c7..0000000 --- a/core/src/instruction/to_bytes.rs +++ /dev/null @@ -1,411 +0,0 @@ -use crate::address_mode::AddressMode; -use crate::address_mode::AddressMode::{Absolute, AbsoluteX, AbsoluteY, Immediate, IndirectX, IndirectY, ZeroPage, ZeroPageX, ZeroPageY}; -use crate::constants::constants_isa_op::*; -use crate::instruction::Instruction; -use crate::instruction::Instruction::*; - -fn split_word_hl(to_split: u16) -> (u8, u8) { - let low = (to_split & 0xff) as u8; - let high = ((to_split & 0xff00) >> 8) as u8; - (high, low) -} - -fn split_word_lh(to_split: u16) -> (u8, u8) { - let low = (to_split & 0xff) as u8; - let high = ((to_split & 0xff00) >> 8) as u8; - (low, high) -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn split_le() { - let value = 0xabcd; - let (high, low) = split_word_hl(value); - - assert_eq!(low, 0xcd); - assert_eq!(high, 0xab); - } - - #[test] - fn split_be() { - let value = 0xabcd; - let (low, high) = split_word_lh(value); - - assert_eq!(low, 0xcd); - assert_eq!(high, 0xab); - } -} - -impl Instruction { - pub fn to_bytes(&self) -> Vec { - match self { - ADC(mode) => { - match mode { - Immediate(value) => - vec![ISA_OP_ADC_I, *value], - - ZeroPage(offset) => - vec![ISA_OP_ADC_Z, *offset], - - ZeroPageX(value) => - vec![ISA_OP_ADC_ZX, *value], - - Absolute(offset) => { - let high = ((offset & 0xff00) >> 8) as u8; - let low = (offset & 0x00ff) as u8; - vec![ISA_OP_ADC_ABS, low, high] - } - AbsoluteX(offset) => { - let high = ((offset & 0xff00) >> 8) as u8; - let low = (offset & 0x00ff) as u8; - vec![ISA_OP_ADC_ABSX, low, high] - } - AbsoluteY(offset) => { - let high = ((offset & 0xff00) >> 8) as u8; - let low = (offset & 0x00ff) as u8; - vec![ISA_OP_ADC_ABSY, low, high] - } - IndirectX(offset) => - vec![ISA_OP_ADC_INDX, *offset], - IndirectY(offset) => - vec![ISA_OP_ADC_INDY, *offset], - _ => { vec![] } - } - } - AND(mode) => { - match mode { - Immediate(value) => vec![ISA_OP_AND_I, *value], - ZeroPage(value) => vec![ISA_OP_AND_Z, *value], - ZeroPageX(value) => vec![ISA_OP_AND_ZX, *value], - Absolute(offset) => { - let (h, l) = split_word_hl(*offset); - vec![ISA_OP_AND_ABS, l, h] - } - AbsoluteX(offset) => { - let (h, l) = split_word_hl(*offset); - vec![ISA_OP_AND_ABSX, l, h] - } - AbsoluteY(offset) => { - let (h, l) = split_word_hl(*offset); - vec![ISA_OP_AND_ABSY, l, h] - } - IndirectX(value) => vec![ISA_OP_AND_INDX, *value], - IndirectY(value) => vec![ISA_OP_AND_INDY, *value], - _ => vec![] - } - } - ASL(mode) => { - match mode { - AddressMode::Accumulator => { - vec![ISA_OP_ASL_A] - } - ZeroPage(value) => { - vec![ISA_OP_ASL_Z, *value] - } - ZeroPageX(value) => { - vec![ISA_OP_ASL_ZX, *value] - } - Absolute(offset) => { - let (h, l) = split_word_hl(*offset); - vec![ISA_OP_ASL_ABS, l, h] - } - AbsoluteX(offset) => { - let (h, l) = split_word_hl(*offset); - vec![ISA_OP_ASL_ABSX, l, h] - } - _ => vec![ISA_OP_NOP] - } - } - BCC(mode) => { - match mode { - Immediate(value) => { - vec![ISA_OP_BCC, *value] - } - _ => vec![ISA_OP_NOP] - } - } - BCS(mode) => { - match mode { - Immediate(value) => { - vec![ISA_OP_BCS, *value] - } - _ => vec![ISA_OP_NOP] - } - } - BEQ(mode) => { - match mode { - Immediate(value) => { - vec![ISA_OP_BEQ, *value] - } - _ => vec![ISA_OP_NOP] - } - } - BIT(mode) => { - match mode { - Absolute(offset) => { - let (h, l) = split_word_hl(*offset); - vec![ISA_OP_BIT_ABS, l, h] - } - ZeroPage(value) => vec![ISA_OP_BIT_ZP, *value], - _ => vec![ISA_OP_NOP] - } - } - BMI(mode) => { - match mode { - Immediate(value) => vec![ISA_OP_BMI, *value], - _ => vec![ISA_OP_NOP] - } - } - BNE(mode) => { - match mode { - Immediate(value) => vec![ISA_OP_BNE, *value], - _ => vec![ISA_OP_NOP] - } - } - BPL(mode) => { - match mode { - Immediate(value) => vec![ISA_OP_BPL, *value], - _ => vec![ISA_OP_NOP] - } - } - BRK => vec![ISA_OP_BRK], - BVC(mode) => { - match mode { - Immediate(value) => vec![ISA_OP_BVC, *value], - _ => vec![ISA_OP_NOP] - } - } - BVS(mode) => { - match mode { - Immediate(value) => vec![ISA_OP_BVS, *value], - _ => vec![ISA_OP_NOP] - } - } - CLC => vec![ISA_OP_CLC], - CLD => vec![ISA_OP_CLD], - CLI => vec![ISA_OP_CLI], - CLV => vec![ISA_OP_CLV], - CMP(mode) => { - match mode { - Immediate(value) => vec![ISA_OP_CMP_I, *value], - ZeroPage(value) => vec![ISA_OP_CMP_ZP, *value], - ZeroPageX(value) => vec![ISA_OP_CMP_ZPX, *value], - Absolute(offset) => { - let (l, h) = split_word_lh(*offset); - vec![ISA_OP_CMP_ABS, l, h] - } - AbsoluteX(offset) => { - let (l, h) = split_word_lh(*offset); - vec![ISA_OP_CMP_ABSX, l, h] - } - IndirectX(value) => vec![ISA_OP_CMP_INDX, *value], - IndirectY(value) => vec![ISA_OP_CMP_INDY, *value], - _ => vec![ISA_OP_NOP] - } - } - CPX(mode) => { - match mode { - Immediate(value) => vec![ISA_OP_CPX_I, *value], - ZeroPage(value) => vec![ISA_OP_CPX_ZP, *value], - Absolute(offset) => { - let (l, h) = split_word_lh(*offset); - vec![ISA_OP_CPX_ABS, l, h] - } - _ => vec![ISA_OP_NOP] - } - } - CPY(mode) => { - match mode { - Immediate(value) => vec![ISA_OP_CPY_I, *value], - ZeroPage(value) => vec![ISA_OP_CPY_ZP, *value], - Absolute(offset) => { - let (l, h) = split_word_lh(*offset); - vec![ISA_OP_CPY_ABS, l, h] - } - _ => vec![ISA_OP_NOP] - } - } - DEC(mode) => match mode { - ZeroPage(value) => vec![ISA_OP_DEC_ZP, *value], - ZeroPageX(value) => vec![ISA_OP_DEC_ZPX, *value], - Absolute(offset) => { - let (l, h) = split_word_lh(*offset); - vec![ISA_OP_DEC_ABS, l, h] - } - AbsoluteX(offset) => { - let (l, h) = split_word_lh(*offset); - vec![ISA_OP_DEC_ABSX, l, h] - } - _ => vec![ISA_OP_NOP] - } - DEX => vec![ISA_OP_DEX], - DEY => vec![ISA_OP_DEY], - EOR(mode) => { - match mode { - Immediate(value) => vec![ISA_OP_EOR_I, *value], - ZeroPage(value) => vec![ISA_OP_EOR_ZP, *value], - ZeroPageX(value) => vec![ISA_OP_EOR_ZPX, *value], - Absolute(offset) => { - let (l, h) = split_word_lh(*offset); - vec![ISA_OP_EOR_ABS, l, h] - } - AbsoluteX(offset) => { - let (l, h) = split_word_lh(*offset); - vec![ISA_OP_EOR_ABSX, l, h] - } - AbsoluteY(offset) => { - let (l, h) = split_word_lh(*offset); - vec![ISA_OP_EOR_ABSY, l, h] - } - IndirectX(value) => vec![ISA_OP_EOR_INDX, *value], - IndirectY(value) => vec![ISA_OP_EOR_INDY, *value], - _ => vec![ISA_OP_NOP] - } - } - INC(mode) => { - match mode { - ZeroPage(value) => vec![ISA_OP_INC_ZP, *value], - ZeroPageX(value) => vec![ISA_OP_INC_ZPX, *value], - Absolute(offset) => { - let (l, h) = split_word_lh(*offset); - vec![ISA_OP_INC_ABS, l, h] - } - AbsoluteX(offset) => { - let (l, h) = split_word_lh(*offset); - vec![ISA_OP_INC_ABSX, l, h] - } - _ => vec![ISA_OP_NOP] - } - } - INX => vec![ISA_OP_INX], - INY => vec![ISA_OP_INY], - JMP(mode) => { - match mode { - Absolute(offset) => { - let (l, h) = split_word_lh(*offset); - vec![ISA_OP_JMP_ABS, l, h] - } - IndirectX(value) => { - vec![ISA_OP_JMP_IND, *value] - } - _ => vec![ISA_OP_NOP] - } - } - JSR(mode) => { - match mode { - Immediate(value) => vec![ISA_OP_JSR, *value], - _ => vec![ISA_OP_NOP] - } - } - LDA(mode) => { - match mode { - Immediate(value) => vec![ISA_OP_LDA_I, *value], - ZeroPage(value) => vec![ISA_OP_LDA_Z, *value], - ZeroPageX(value) => vec![ISA_OP_LDA_ZX, *value], - Absolute(offset) => { - let (l, h) = split_word_lh(*offset); - vec![ISA_OP_LDA_ABS, l, h] - } - AbsoluteX(offset) => { - let (l, h) = split_word_lh(*offset); - vec![ISA_OP_LDA_ABSX, l, h] - } - AbsoluteY(offset) => { - let (l, h) = split_word_lh(*offset); - vec![ISA_OP_LDA_ABSY, l, h] - } - IndirectX(value) => vec![ISA_OP_LDA_INDX, *value], - IndirectY(value) => vec![ISA_OP_LDA_INDY, *value], - _ => vec![ISA_OP_NOP] - } - } - LDX(mode) => { - match mode { - Immediate(value) => vec![ISA_OP_LDX_I, *value], - ZeroPage(value) => vec![ISA_OP_LDX_ZP, *value], - ZeroPageY(value) => vec![ISA_OP_LDX_ZPY, *value], - Absolute(offset) => { - let (l, h) = split_word_lh(*offset); - vec![ISA_OP_LDX_ABS, l, h] - } - AbsoluteY(offset) => { - let (l, h) = split_word_lh(*offset); - vec![ISA_OP_LDX_ABSY, l, h] - } - _ => vec![ISA_OP_NOP] - } - } - LDY(mode) => { - match mode { - Immediate(value) => vec![ISA_OP_LDY_I, *value], - ZeroPage(value) => vec![ISA_OP_LDY_ZP, *value], - ZeroPageX(value) => vec![ISA_OP_LDY_ZPX, *value], - Absolute(offset) => { - let (l, h) = split_word_lh(*offset); - vec![ISA_OP_LDY_ABS, l, h] - } - AbsoluteY(offset) => { - let (l, h) = split_word_lh(*offset); - vec![ISA_OP_LDY_ABSX, l, h] - } - _ => vec![ISA_OP_NOP] - }} - // LSR(_) => {} - NOP => vec![ISA_OP_NOP], - // ORA(_) => {} - PHA => vec![ISA_OP_PHA], - PHP => vec![ISA_OP_PHP], - PLA => vec![ISA_OP_PLA], - PLP => vec![ISA_OP_PLP], - // ROL(_) => {} - // ROR(_) => {} - RTI => vec![ISA_OP_RTI], - RTS => vec![ISA_OP_RTS], - // SBC(_) => {} - SEC => vec![ISA_OP_SEC], - SED => vec![ISA_OP_SED], - SEI => vec![ISA_OP_SEI], - // STA(_) => {} - STX(mode) => { - match mode { - ZeroPage(value) => { - vec![ISA_OP_STX_ZP, *value] - } - ZeroPageX(value) => { - vec![ISA_OP_STX_ZPX, *value] - } - Absolute(offset) => { - let (h, l) = split_word_hl(*offset); - vec![ISA_OP_STX_ABS, l, h] - } - _ => vec![ISA_OP_NOP] - } - } - STY(mode) => { - match mode { - ZeroPage(value) => { - vec![ISA_OP_STY_ZP, *value] - } - ZeroPageX(value) => { - vec![ISA_OP_STY_ZPX, *value] - } - Absolute(offset) => { - let (h, l) = split_word_hl(*offset); - vec![ISA_OP_STY_ABS, l, h] - } - _ => vec![ISA_OP_NOP] - } - } - TAX => vec![ISA_OP_TAX], - TAY => vec![ISA_OP_TAY], - TSX => vec![ISA_OP_TSX], - TXA => vec![ISA_OP_TXA], - TXS => vec![ISA_OP_TXS], - TYA => vec![ISA_OP_TYA], - _ => { vec![] } - } - } -} \ No newline at end of file diff --git a/core/src/instruction/to_string.rs b/core/src/instruction/to_string.rs deleted file mode 100644 index 9d9b0ce..0000000 --- a/core/src/instruction/to_string.rs +++ /dev/null @@ -1,42 +0,0 @@ -use crate::address_mode::AddressMode; -use crate::address_mode::AddressMode::Implied; -use crate::instruction::Instruction; -use crate::instruction::Instruction::*; - -impl Instruction { - pub fn to_string(&self) -> String { - let mode = match self { - ADC(newmode) | AND(newmode) | ASL(newmode) | - BCC(newmode) | BCS(newmode) | BEQ(newmode) | - BIT(newmode) | BMI(newmode) | BNE(newmode) | - BPL(newmode) | BVC(newmode) | BVS(newmode) | - CMP(newmode) | CPX(newmode) | CPY(newmode) | - DEC(newmode) | EOR(newmode) | INC(newmode) | - JMP(newmode) | JSR(newmode) | LDA(newmode) | - LDX(newmode) | LDY(newmode) | LSR(newmode) | - ORA(newmode) | ROL(newmode) | ROR(newmode) | - SBC(newmode) | STA(newmode) | STX(newmode) | - STY(newmode) => newmode, - _ => &Implied - }; - - Instruction::format(mode, &self.stub()) - } - - fn format(mode: &AddressMode, prefix: &str) -> String { - let suffix = match mode { - AddressMode::Implied => "", - AddressMode::Accumulator => " A", - AddressMode::Immediate(value) => &*format!(" #${value:02x}"), - AddressMode::ZeroPage(value) => &*format!(" ${value:02x}"), - AddressMode::ZeroPageX(value) => &*format!(" ${value:02x},X"), - AddressMode::Absolute(offset) => &*format!(" ${offset:04x}"), - AddressMode::AbsoluteX(offset) => &*format!(" ${offset:04x},X"), - AddressMode::AbsoluteY(offset) => &*format!(" ${offset:04x},Y"), - AddressMode::IndirectX(value) => &*format!(" (${value:02x},X)"), - AddressMode::IndirectY(value) => &*format!(" (${value:02x}),Y"), - AddressMode::ZeroPageY(value) => &*format!(" ${value:02x},Y") - }; - format!("{}{}", prefix, suffix) - } -} \ No newline at end of file diff --git a/core/src/instruction2/from_bytes.rs b/core/src/instruction2/from_bytes.rs new file mode 100644 index 0000000..3706319 --- /dev/null +++ b/core/src/instruction2/from_bytes.rs @@ -0,0 +1,23 @@ +use log::debug; +use crate::address_mode::AddressMode::*; +use crate::constants::constants_isa_op::*; + +fn join_word(low: u8, high: u8) -> u16 { + ((high as u16) << 8) | low as u16 +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_join_word() { + let low: u8 = 0xcd; + let high: u8 = 0xab; + + assert_eq!( + join_word(low, high), + 0xabcd + ); + } +} diff --git a/core/src/instruction2/mod.rs b/core/src/instruction2/mod.rs new file mode 100644 index 0000000..9de61ef --- /dev/null +++ b/core/src/instruction2/mod.rs @@ -0,0 +1,7 @@ +use crate::address_mode::AddressMode; +use crate::address_mode::AddressMode::*; +use crate::mos6502flags::Mos6502Flag::*; + +mod from_bytes; +mod to_bytes; +mod to_string; diff --git a/core/src/instruction2/to_bytes.rs b/core/src/instruction2/to_bytes.rs new file mode 100644 index 0000000..451e74e --- /dev/null +++ b/core/src/instruction2/to_bytes.rs @@ -0,0 +1,38 @@ +use crate::address_mode::AddressMode; +use crate::address_mode::AddressMode::{Absolute, AbsoluteX, AbsoluteY, Immediate, IndirectX, IndirectY, ZeroPage, ZeroPageX, ZeroPageY}; +use crate::constants::constants_isa_op::*; + +fn split_word_hl(to_split: u16) -> (u8, u8) { + let low = (to_split & 0xff) as u8; + let high = ((to_split & 0xff00) >> 8) as u8; + (high, low) +} + +fn split_word_lh(to_split: u16) -> (u8, u8) { + let low = (to_split & 0xff) as u8; + let high = ((to_split & 0xff00) >> 8) as u8; + (low, high) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn split_le() { + let value = 0xabcd; + let (high, low) = split_word_hl(value); + + assert_eq!(low, 0xcd); + assert_eq!(high, 0xab); + } + + #[test] + fn split_be() { + let value = 0xabcd; + let (low, high) = split_word_lh(value); + + assert_eq!(low, 0xcd); + assert_eq!(high, 0xab); + } +} diff --git a/core/src/instruction2/to_string.rs b/core/src/instruction2/to_string.rs new file mode 100644 index 0000000..ff6606a --- /dev/null +++ b/core/src/instruction2/to_string.rs @@ -0,0 +1,18 @@ + +fn format(mode: &AddressMode, prefix: &str) -> String { + // let suffix = match mode { + // AddressMode::Implied => "", + // AddressMode::Accumulator => " A", + // AddressMode::Immediate(value) => &*format!(" #${value:02x}"), + // AddressMode::ZeroPage(value) => &*format!(" ${value:02x}"), + // AddressMode::ZeroPageX(value) => &*format!(" ${value:02x},X"), + // AddressMode::Absolute(offset) => &*format!(" ${offset:04x}"), + // AddressMode::AbsoluteX(offset) => &*format!(" ${offset:04x},X"), + // AddressMode::AbsoluteY(offset) => &*format!(" ${offset:04x},Y"), + // AddressMode::IndirectX(value) => &*format!(" (${value:02x},X)"), + // AddressMode::IndirectY(value) => &*format!(" (${value:02x}),Y"), + // AddressMode::ZeroPageY(value) => &*format!(" ${value:02x},Y") + // }; + // format!("{}{}", prefix, suffix) + prefix.to_string() +} \ No newline at end of file diff --git a/core/src/instruction_table.rs b/core/src/instruction_table.rs new file mode 100644 index 0000000..615e95c --- /dev/null +++ b/core/src/instruction_table.rs @@ -0,0 +1,938 @@ +use crate::address_mode::AddressMode; +use crate::constants::constants_isa_op::{ISA_OP_ADC_ABS, ISA_OP_ADC_ABSX, ISA_OP_ADC_ABSY, ISA_OP_ADC_I, ISA_OP_ADC_INDX, ISA_OP_ADC_INDY, ISA_OP_ADC_Z, ISA_OP_ADC_ZX, ISA_OP_AND_ABS, ISA_OP_AND_ABSX, ISA_OP_AND_ABSY, ISA_OP_AND_I, ISA_OP_AND_INDX, ISA_OP_AND_INDY, ISA_OP_AND_Z, ISA_OP_AND_ZX, ISA_OP_ASL_A, ISA_OP_ASL_ABS, ISA_OP_ASL_ABSX, ISA_OP_ASL_Z, ISA_OP_ASL_ZX, ISA_OP_BCC, ISA_OP_BCS, ISA_OP_BEQ, ISA_OP_BIT_ABS, ISA_OP_BIT_ZP, ISA_OP_BMI, ISA_OP_BNE, ISA_OP_BPL, ISA_OP_BRK, ISA_OP_BVC, ISA_OP_BVS, ISA_OP_CLC, ISA_OP_CLD, ISA_OP_CLI, ISA_OP_CLV, ISA_OP_CMP_ABS, ISA_OP_CMP_ABSX, ISA_OP_CMP_ABSY, ISA_OP_CMP_I, ISA_OP_CMP_INDX, ISA_OP_CMP_INDY, ISA_OP_CMP_ZP, ISA_OP_CMP_ZPX, ISA_OP_CPX_ABS, ISA_OP_CPX_I, ISA_OP_CPX_ZP, ISA_OP_CPY_ABS, ISA_OP_CPY_I, ISA_OP_CPY_ZP, ISA_OP_DEC_ABS, ISA_OP_DEC_ABSX, ISA_OP_DEC_ZP, ISA_OP_DEC_ZPX, ISA_OP_DEX, ISA_OP_DEY, ISA_OP_EOR_ABS, ISA_OP_EOR_ABSX, ISA_OP_EOR_ABSY, ISA_OP_EOR_I, ISA_OP_EOR_INDX, ISA_OP_EOR_ZP, ISA_OP_EOR_ZPX, ISA_OP_INC_ABS, ISA_OP_INC_ABSX, ISA_OP_INC_ZP, ISA_OP_INC_ZPX, ISA_OP_INX, ISA_OP_INY, ISA_OP_JMP_ABS, ISA_OP_JMP_IND, ISA_OP_JSR, ISA_OP_LDA_ABS, ISA_OP_LDA_ABSX, ISA_OP_LDA_ABSY, ISA_OP_LDA_I, ISA_OP_LDA_INDX, ISA_OP_LDA_INDY, ISA_OP_LDA_Z, ISA_OP_LDA_ZX, ISA_OP_LDX_ABS, ISA_OP_LDX_ABSY, ISA_OP_LDX_I, ISA_OP_LDX_ZP, ISA_OP_LDX_ZPY, ISA_OP_LDY_ABS, ISA_OP_LDY_ABSX, ISA_OP_LDY_I, ISA_OP_LDY_ZP, ISA_OP_LDY_ZPX, ISA_OP_LSR_A, ISA_OP_LSR_ABS, ISA_OP_LSR_ABSX, ISA_OP_LSR_ZP, ISA_OP_LSR_ZPX, ISA_OP_NOP, ISA_OP_ORA_ABS, ISA_OP_ORA_ABSY, ISA_OP_ORA_I, ISA_OP_ORA_INDX, ISA_OP_ORA_INDY, ISA_OP_ORA_ZP, ISA_OP_ORA_ZPX, ISA_OP_PHA, ISA_OP_PHP, ISA_OP_PLA, ISA_OP_PLP, ISA_OP_ROL_A, ISA_OP_ROL_ABS, ISA_OP_ROL_ABSX, ISA_OP_ROL_ZP, ISA_OP_ROL_ZPX, ISA_OP_ROR_A, ISA_OP_ROR_ABS, ISA_OP_ROR_ABSX, ISA_OP_ROR_ZP, ISA_OP_ROR_ZPX, ISA_OP_RTI, ISA_OP_RTS, ISA_OP_SBC_ABS, ISA_OP_SBC_ABSX, ISA_OP_SBC_ABSY, ISA_OP_SBC_I, ISA_OP_SBC_INDX, ISA_OP_SBC_INDY, ISA_OP_SBC_ZP, ISA_OP_SBC_ZPX, ISA_OP_SEC, ISA_OP_SED, ISA_OP_SEI, ISA_OP_STA_ABS, ISA_OP_STA_ABSX, ISA_OP_STA_ABSY, ISA_OP_STA_INDX, ISA_OP_STA_INDY, ISA_OP_STA_ZP, ISA_OP_STA_ZPX, ISA_OP_STX_ABS, ISA_OP_STX_ZP, ISA_OP_STX_ZPY, ISA_OP_STY_ABS, ISA_OP_STY_ZP, ISA_OP_STY_ZPX, ISA_OP_TAX, ISA_OP_TAY, ISA_OP_TSX, ISA_OP_TXA, ISA_OP_TXS, ISA_OP_TYA}; +use crate::op_info::OpInfo; +use crate::operation::Operation; +use crate::operation::Operation::*; + +pub const INSTRUCTION_TABLE: [Option; 256] = { + let mut table: [Option; 256] = [const { None }; 256]; + + table[ISA_OP_ADC_I as usize] = Some(OpInfo { + operation: ADC, + mode: AddressMode::Immediate, + length: 2, + cycles: 2, + }); + table[ISA_OP_ADC_Z as usize] = Some(OpInfo { + operation: ADC, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 3, + }); + table[ISA_OP_ADC_ZX as usize] = Some(OpInfo { + operation: ADC, + mode: AddressMode::ZeroPageX, + length: 2, + cycles: 4, + }); + table[ISA_OP_ADC_ABS as usize] = Some(OpInfo { + operation: ADC, + mode: AddressMode::Absolute, + length: 3, + cycles: 4, + }); + table[ISA_OP_ADC_ABSX as usize] = Some(OpInfo { + operation: ADC, + mode: AddressMode::AbsoluteX, + length: 3, + cycles: 4, + }); + table[ISA_OP_ADC_ABSY as usize] = Some(OpInfo { + operation: ADC, + mode: AddressMode::AbsoluteY, + length: 3, + cycles: 4, + }); + table[ISA_OP_ADC_INDX as usize] = Some(OpInfo { + operation: ADC, + mode: AddressMode::IndirectX, + length: 2, + cycles: 6, + }); + table[ISA_OP_ADC_INDY as usize] = Some(OpInfo { + operation: ADC, + mode: AddressMode::IndirectY, + length: 2, + cycles: 5, + }); + + table[ISA_OP_AND_I as usize] = Some(OpInfo { + operation: AND, + mode: AddressMode::Immediate, + length: 2, + cycles: 2, + }); + table[ISA_OP_AND_Z as usize] = Some(OpInfo { + operation: AND, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 3, + }); + table[ISA_OP_AND_ZX as usize] = Some(OpInfo { + operation: AND, + mode: AddressMode::ZeroPageX, + length: 2, + cycles: 4, + }); + table[ISA_OP_AND_ABS as usize] = Some(OpInfo { + operation: AND, + mode: AddressMode::Absolute, + length: 3, + cycles: 4, + }); + table[ISA_OP_AND_ABSX as usize] = Some(OpInfo { + operation: AND, + mode: AddressMode::AbsoluteX, + length: 3, + cycles: 4, + }); + table[ISA_OP_AND_ABSY as usize] = Some(OpInfo { + operation: AND, + mode: AddressMode::AbsoluteY, + length: 3, + cycles: 4, + }); + table[ISA_OP_AND_INDX as usize] = Some(OpInfo { + operation: AND, + mode: AddressMode::IndirectX, + length: 2, + cycles: 6, + }); + table[ISA_OP_AND_INDY as usize] = Some(OpInfo { + operation: AND, + mode: AddressMode::IndirectY, + length: 2, + cycles: 5, + }); + table[ISA_OP_ASL_A as usize] = Some(OpInfo { + operation: ASL, + mode: AddressMode::Accumulator, + length: 1, + cycles: 2, + }); + table[ISA_OP_ASL_Z as usize] = Some(OpInfo { + operation: ASL, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 5, + }); + table[ISA_OP_ASL_ZX as usize] = Some(OpInfo { + operation: ASL, + mode: AddressMode::ZeroPageX, + length: 2, + cycles: 6, + }); + table[ISA_OP_ASL_ABS as usize] = Some(OpInfo { + operation: ASL, + mode: AddressMode::Absolute, + length: 3, + cycles: 6, + }); + table[ISA_OP_ASL_ABSX as usize] = Some(OpInfo { + operation: ASL, + mode: AddressMode::AbsoluteX, + length: 3, + cycles: 7, + }); + + table[ISA_OP_BCC as usize] = Some(OpInfo { + operation: BCC, + mode: AddressMode::Implied, + length: 2, + cycles: 2, + }); + table[ISA_OP_BCS as usize] = Some(OpInfo { + operation: BCS, + mode: AddressMode::Implied, + length: 2, + cycles: 2, + }); + table[ISA_OP_BEQ as usize] = Some(OpInfo { + operation: BEQ, + mode: AddressMode::Implied, + length: 2, + cycles: 2, + }); + + table[ISA_OP_BIT_ZP as usize] = Some(OpInfo { + operation: BIT, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 3, + }); + table[ISA_OP_BIT_ABS as usize] = Some(OpInfo { + operation: BIT, + mode: AddressMode::Absolute, + length: 3, + cycles: 4, + }); + + table[ISA_OP_BMI as usize] = Some(OpInfo { + operation: BMI, + mode: AddressMode::Implied, + length: 2, + cycles: 2, + }); + + table[ISA_OP_BNE as usize] = Some(OpInfo { + operation: BNE, + mode: AddressMode::Implied, + length: 2, + cycles: 2, + }); + + table[ISA_OP_BPL as usize] = Some(OpInfo { + operation: Operation::BPL, + mode: AddressMode::Implied, + length: 2, + cycles: 2, + }); + table[ISA_OP_BRK as usize] = Some(OpInfo { + operation: BRK, + mode: AddressMode::Implied, + length: 1, + cycles: 7, + }); + table[ISA_OP_BVC as usize] = Some(OpInfo { + operation: BVC, + mode: AddressMode::Implied, + length: 2, + cycles: 2, + }); + table[ISA_OP_BVS as usize] = Some(OpInfo { + operation: BVS, + mode: AddressMode::Implied, + length: 2, + cycles: 2, + }); + table[ISA_OP_CLC as usize] = Some(OpInfo { + operation: CLC, + mode: AddressMode::Implied, + length: 1, + cycles: 2, + }); + table[ISA_OP_CLD as usize] = Some(OpInfo { + operation: CLD, + mode: AddressMode::Implied, + length: 1, + cycles: 2, + }); + table[ISA_OP_CLI as usize] = Some(OpInfo { + operation: CLI, + mode: AddressMode::Implied, + length: 1, + cycles: 2, + }); + table[ISA_OP_CLV as usize] = Some(OpInfo { + operation: CLV, + mode: AddressMode::Implied, + length: 2, + cycles: 1, + }); + + table[ISA_OP_CMP_I as usize] = Some(OpInfo { + operation: CMP, + mode: AddressMode::Immediate, + length: 2, + cycles: 2, + }); + table[ISA_OP_CMP_ZP as usize] = Some(OpInfo { + operation: CMP, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 3, + }); + table[ISA_OP_CMP_ZPX as usize] = Some(OpInfo { + operation: CMP, + mode: AddressMode::ZeroPageX, + length: 2, + cycles: 4, + }); + table[ISA_OP_CMP_ABS as usize] = Some(OpInfo { + operation: CMP, + mode: AddressMode::Absolute, + length: 3, + cycles: 4, + }); + table[ISA_OP_CMP_ABSX as usize] = Some(OpInfo { + operation: CMP, + mode: AddressMode::AbsoluteX, + length: 2, + cycles: 4, + }); + table[ISA_OP_CMP_ABSY as usize] = Some(OpInfo { + operation: CMP, + mode: AddressMode::AbsoluteY, + length: 2, + cycles: 4, + }); + table[ISA_OP_CMP_INDX as usize] = Some(OpInfo { + operation: CMP, + mode: AddressMode::IndirectX, + length: 2, + cycles: 6, + }); + table[ISA_OP_CMP_INDY as usize] = Some(OpInfo { + operation: CMP, + mode: AddressMode::IndirectY, + length: 2, + cycles: 5, + }); + + table[ISA_OP_CPX_I as usize] = Some(OpInfo { + operation: CPX, + mode: AddressMode::Immediate, + length: 2, + cycles: 2, + }); + table[ISA_OP_CPX_ZP as usize] = Some(OpInfo { + operation: CPX, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 3, + }); + table[ISA_OP_CPX_ABS as usize] = Some(OpInfo { + operation: CPX, + mode: AddressMode::Absolute, + length: 3, + cycles: 4, + }); + table[ISA_OP_CPY_I as usize] = Some(OpInfo { + operation: CPY, + mode: AddressMode::Immediate, + length: 2, + cycles: 2, + }); + table[ISA_OP_CPY_ZP as usize] = Some(OpInfo { + operation: CPY, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 3, + }); + table[ISA_OP_CPY_ABS as usize] = Some(OpInfo { + operation: CPY, + mode: AddressMode::Absolute, + length: 3, + cycles: 4, + }); + + table[ISA_OP_DEC_ZP as usize] = Some(OpInfo { + operation: DEC, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 5, + }); + table[ISA_OP_DEC_ZPX as usize] = Some(OpInfo { + operation: DEC, + mode: AddressMode::ZeroPageX, + length: 2, + cycles: 6, + }); + table[ISA_OP_DEC_ABS as usize] = Some(OpInfo { + operation: DEC, + mode: AddressMode::Absolute, + length: 3, + cycles: 6, + }); + table[ISA_OP_DEC_ABSX as usize] = Some(OpInfo { + operation: DEC, + mode: AddressMode::AbsoluteX, + length: 3, + cycles: 7, + }); + table[ISA_OP_DEX as usize] = Some(OpInfo { + operation: DEX, + mode: AddressMode::Implied, + length: 1, + cycles: 2, + }); + table[ISA_OP_DEY as usize] = Some(OpInfo { + operation: DEY, + mode: AddressMode::Implied, + length: 1, + cycles: 2, + }); + table[ISA_OP_EOR_I as usize] = Some(OpInfo { + operation: EOR, + mode: AddressMode::Immediate, + length: 2, + cycles: 2, + }); + table[ISA_OP_EOR_ZP as usize] = Some(OpInfo { + operation: EOR, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 3, + }); + table[ISA_OP_EOR_ZPX as usize] = Some(OpInfo { + operation: EOR, + mode: AddressMode::ZeroPageX, + length: 2, + cycles: 4, + }); + table[ISA_OP_EOR_ABS as usize] = Some(OpInfo { + operation: EOR, + mode: AddressMode::Absolute, + length: 3, + cycles: 4, + }); + table[ISA_OP_EOR_ABSX as usize] = Some(OpInfo { + operation: EOR, + mode: AddressMode::AbsoluteX, + length: 3, + cycles: 4, + }); + table[ISA_OP_EOR_ABSX as usize] = Some(OpInfo { + operation: EOR, + mode: AddressMode::AbsoluteY, + length: 3, + cycles: 4, + }); + table[ISA_OP_EOR_INDX as usize] = Some(OpInfo { + operation: EOR, + mode: AddressMode::IndirectX, + length: 2, + cycles: 6, + }); + table[ISA_OP_EOR_ABSY as usize] = Some(OpInfo { + operation: EOR, + mode: AddressMode::IndirectY, + length: 2, + cycles: 5, + }); + + table[ISA_OP_INC_ZP as usize] = Some(OpInfo { + operation: INC, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 5, + }); + table[ISA_OP_INC_ZPX as usize] = Some(OpInfo { + operation: INC, + mode: AddressMode::ZeroPageX, + length: 2, + cycles: 6, + }); + table[ISA_OP_INC_ABS as usize] = Some(OpInfo { + operation: INC, + mode: AddressMode::Absolute, + length: 3, + cycles: 6, + }); + table[ISA_OP_INC_ABSX as usize] = Some(OpInfo { + operation: INC, + mode: AddressMode::ZeroPageX, + length: 3, + cycles: 7, + }); + table[ISA_OP_INX as usize] = Some(OpInfo { + operation: INX, + mode: AddressMode::Implied, + length: 1, + cycles: 2, + }); + table[ISA_OP_INY as usize] = Some(OpInfo { + operation: INY, + mode: AddressMode::Implied, + length: 1, + cycles: 2, + }); + table[ISA_OP_JMP_ABS as usize] = Some(OpInfo { + operation: JMP, + mode: AddressMode::Absolute, + length: 3, + cycles: 3, + }); + table[ISA_OP_JMP_IND as usize] = Some(OpInfo { + operation: JMP, + mode: AddressMode::Indirect, + length: 3, + cycles: 5, + }); + table[ISA_OP_JSR as usize] = Some(OpInfo { + operation: JSR, + mode: AddressMode::Absolute, + length: 3, + cycles: 6, + }); + + table[ISA_OP_LDA_I as usize] = Some(OpInfo { + operation: Operation::LDA, + mode: AddressMode::Immediate, + length: 2, + cycles: 2, + }); + table[ISA_OP_LDA_Z as usize] = Some(OpInfo { + operation: LDA, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 3, + }); + table[ISA_OP_LDA_ZX as usize] = Some(OpInfo { + operation: LDA, + mode: AddressMode::ZeroPageX, + length: 2, + cycles: 4, + }); + table[ISA_OP_LDA_ABS as usize] = Some(OpInfo { + operation: Operation::LDA, + mode: AddressMode::Absolute, + length: 3, + cycles: 4, + }); + table[ISA_OP_LDA_ABSX as usize] = Some(OpInfo { + operation: LDA, + mode: AddressMode::AbsoluteX, + length: 3, + cycles: 4, + }); + table[ISA_OP_LDA_ABSY as usize] = Some(OpInfo { + operation: LDA, + mode: AddressMode::AbsoluteY, + length: 3, + cycles: 4, + }); + table[ISA_OP_LDA_INDX as usize] = Some(OpInfo { + operation: Operation::LDA, + mode: AddressMode::IndirectX, + length: 2, + cycles: 6, + }); + table[ISA_OP_LDA_INDY as usize] = Some(OpInfo { + operation: LDA, + mode: AddressMode::IndirectY, + length: 2, + cycles: 5, + }); + + table[ISA_OP_LDX_I as usize] = Some(OpInfo { + operation: Operation::LDX, + mode: AddressMode::Immediate, + length: 2, + cycles: 2, + }); + table[ISA_OP_LDX_ZP as usize] = Some(OpInfo { + operation: Operation::LDX, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 3, + }); + table[ISA_OP_LDX_ZPY as usize] = Some(OpInfo { + operation: LDX, + mode: AddressMode::ZeroPageY, + length: 2, + cycles: 4, + }); + table[ISA_OP_LDX_ABS as usize] = Some(OpInfo { + operation: Operation::LDX, + mode: AddressMode::Absolute, + length: 3, + cycles: 4, + }); + table[ISA_OP_LDX_ABSY as usize] = Some(OpInfo { + operation: Operation::LDX, + mode: AddressMode::AbsoluteY, + length: 3, + cycles: 4, + }); + + table[ISA_OP_LDY_I as usize] = Some(OpInfo { + operation: Operation::LDY, + mode: AddressMode::Immediate, + length: 2, + cycles: 2, + }); + table[ISA_OP_LDY_ZP as usize] = Some(OpInfo { + operation: Operation::LDY, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 3, + }); + table[ISA_OP_LDY_ZPX as usize] = Some(OpInfo { + operation: Operation::LDY, + mode: AddressMode::ZeroPageX, + length: 2, + cycles: 4, + }); + table[ISA_OP_LDY_ABS as usize] = Some(OpInfo { + operation: Operation::LDY, + mode: AddressMode::Absolute, + length: 3, + cycles: 4, + }); + table[ISA_OP_LDY_ABSX as usize] = Some(OpInfo { + operation: Operation::LDY, + mode: AddressMode::AbsoluteX, + length: 3, + cycles: 4, + }); + + table[ISA_OP_LSR_A as usize] = Some(OpInfo { + operation: Operation::LSR, + mode: AddressMode::Accumulator, + length: 1, + cycles: 2, + }); + table[ISA_OP_LSR_ZP as usize] = Some(OpInfo { + operation: Operation::LSR, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 5, + }); + table[ISA_OP_LSR_ZPX as usize] = Some(OpInfo { + operation: Operation::LSR, + mode: AddressMode::ZeroPageX, + length: 2, + cycles: 6, + }); + table[ISA_OP_LSR_ABS as usize] = Some(OpInfo { + operation: Operation::LSR, + mode: AddressMode::Absolute, + length: 3, + cycles: 6, + }); + table[ISA_OP_LSR_ABSX as usize] = Some(OpInfo { + operation: Operation::LSR, + mode: AddressMode::AbsoluteX, + length: 3, + cycles: 7, + }); + + table[ISA_OP_NOP as usize] = Some(OpInfo { + operation: Operation::NOP, + mode: AddressMode::Implied, + length: 1, + cycles: 2, + }); + + table[ISA_OP_ORA_I as usize] = Some(OpInfo { + operation: Operation::ORA, + mode: AddressMode::Immediate, + length: 2, + cycles: 2, + }); + table[ISA_OP_ORA_ZP as usize] = Some(OpInfo { + operation: Operation::ORA, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 3, + }); + table[ISA_OP_ORA_ZPX as usize] = Some(OpInfo { + operation: Operation::ORA, + mode: AddressMode::ZeroPageX, + length: 2, + cycles: 4, + }); + table[ISA_OP_ORA_ABS as usize] = Some(OpInfo { + operation: Operation::ORA, + mode: AddressMode::Absolute, + length: 3, + cycles: 4, + }); + table[ISA_OP_ORA_ABSY as usize] = Some(OpInfo { + operation: Operation::ORA, + mode: AddressMode::AbsoluteY, + length: 3, + cycles: 4, + }); + table[ISA_OP_ORA_INDX as usize] = Some(OpInfo { + operation: Operation::ORA, + mode: AddressMode::IndirectX, + length: 2, + cycles: 6, + }); + table[ISA_OP_ORA_INDY as usize] = Some(OpInfo { + operation: Operation::ORA, + mode: AddressMode::IndirectY, + length: 2, + cycles: 5, + }); + + table[ISA_OP_PHA as usize] = Some(OpInfo { + operation: PHA, + mode: AddressMode::Implied, + length: 1, + cycles: 3, + }); + table[ISA_OP_PHP as usize] = Some(OpInfo { + operation: Operation::PHP, + mode: AddressMode::Implied, + length: 1, + cycles: 3, + }); + table[ISA_OP_PLA as usize] = Some(OpInfo { + operation: Operation::PLA, + mode: AddressMode::Implied, + length: 1, + cycles: 4, + }); + table[ISA_OP_PLP as usize] = Some(OpInfo { + operation: Operation::PLP, + mode: AddressMode::Implied, + length: 1, + cycles: 4, + }); + + table[ISA_OP_ROL_A as usize] = Some(OpInfo { + operation: Operation::ROL, + mode: AddressMode::Accumulator, + length: 1, + cycles: 2, + }); + table[ISA_OP_ROL_ZP as usize] = Some(OpInfo { + operation: Operation::ROL, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 5, + }); + table[ISA_OP_ROL_ZPX as usize] = Some(OpInfo { + operation: Operation::ROL, + mode: AddressMode::ZeroPageX, + length: 2, + cycles: 6, + }); + table[ISA_OP_ROL_ABS as usize] = Some(OpInfo { + operation: Operation::ROL, + mode: AddressMode::Absolute, + length: 3, + cycles: 6, + }); + table[ISA_OP_ROL_ABSX as usize] = Some(OpInfo { + operation: Operation::ROL, + mode: AddressMode::AbsoluteX, + length: 3, + cycles: 7, + }); + + table[ISA_OP_ROR_A as usize] = Some(OpInfo { + operation: Operation::ROR, + mode: AddressMode::Accumulator, + length: 1, + cycles: 2 + }); + table[ISA_OP_ROR_ZP as usize] = Some(OpInfo { + operation: Operation::ROR, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 5, + }); + table[ISA_OP_ROR_ZPX as usize] = Some(OpInfo { + operation: Operation::ROR, + mode: AddressMode::ZeroPageX, + length: 2, + cycles: 6, + }); + table[ISA_OP_ROR_ABS as usize] = Some(OpInfo { + operation: Operation::ROR, + mode: AddressMode::Absolute, + length: 3, + cycles: 6, + }); + table[ISA_OP_ROR_ABSX as usize] = Some(OpInfo { + operation: Operation::ROR, + mode: AddressMode::AbsoluteX, + length: 3, + cycles: 7, + }); + + table[ISA_OP_RTI as usize] = Some(OpInfo { + operation: Operation::RTI, + mode: AddressMode::Implied, + length: 1, + cycles: 2, + }); + table[ISA_OP_RTS as usize] = Some(OpInfo { + operation: Operation::RTS, + mode: AddressMode::Implied, + length: 1, + cycles: 2, + }); + + table[ISA_OP_SBC_I as usize] = Some(OpInfo { + operation: Operation::SBC, + mode: AddressMode::Immediate, + length: 2, + cycles: 2, + }); + table[ISA_OP_SBC_ZP as usize] = Some(OpInfo { + operation: Operation::SBC, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 3, + }); + table[ISA_OP_SBC_ZPX as usize] = Some(OpInfo { + operation: Operation::SBC, + mode: AddressMode::ZeroPageX, + length: 2, + cycles: 4, + }); + table[ISA_OP_SBC_ABS as usize] = Some(OpInfo { + operation: Operation::SBC, + mode: AddressMode::Absolute, + length: 3, + cycles: 4, + }); + table[ISA_OP_SBC_ABSX as usize] = Some(OpInfo { + operation: Operation::SBC, + mode: AddressMode::AbsoluteX, + length: 3, + cycles: 4, + }); + table[ISA_OP_SBC_ABSY as usize] = Some(OpInfo { + operation: Operation::SBC, + mode: AddressMode::AbsoluteY, + length: 3, + cycles: 4, + }); + table[ISA_OP_SBC_INDX as usize] = Some(OpInfo { + operation: Operation::SBC, + mode: AddressMode::IndirectX, + length: 2, + cycles: 6, + }); + table[ISA_OP_SBC_INDY as usize] = Some(OpInfo { + operation: Operation::SBC, + mode: AddressMode::IndirectY, + length: 2, + cycles: 5, + }); + + table[ISA_OP_SEC as usize] = Some(OpInfo { + operation: SEC, + mode: AddressMode::Implied, + length: 1, + cycles: 2, + }); + table[ISA_OP_SED as usize] = Some(OpInfo { + operation: Operation::SED, + mode: AddressMode::Implied, + length: 1, + cycles: 2, + }); + table[ISA_OP_SEI as usize] = Some(OpInfo { + operation: Operation::SEI, + mode: AddressMode::Implied, + length: 1, + cycles: 2, + }); + + table[ISA_OP_STA_ZP as usize] = Some(OpInfo { + operation: Operation::STA, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 3, + }); + table[ISA_OP_STA_ZPX as usize] = Some(OpInfo { + operation: Operation::STA, + mode: AddressMode::ZeroPageX, + length: 2, + cycles: 4, + }); + table[ISA_OP_STA_ABS as usize] = Some(OpInfo { + operation: Operation::STA, + mode: AddressMode::Absolute, + length: 3, + cycles: 4, + }); + table[ISA_OP_STA_ABSX as usize] = Some(OpInfo { + operation: STA, + mode: AddressMode::AbsoluteX, + length: 3, + cycles: 5, + }); + table[ISA_OP_STA_ABSY as usize] = Some(OpInfo { + operation: Operation::STA, + mode: AddressMode::AbsoluteY, + length: 3, + cycles: 5, + }); + table[ISA_OP_STA_INDX as usize] = Some(OpInfo { + operation: Operation::STA, + mode: AddressMode::IndirectX, + length: 2, + cycles: 6, + }); + table[ISA_OP_STA_INDY as usize] = Some(OpInfo { + operation: Operation::STA, + mode: AddressMode::IndirectY, + length: 2, + cycles: 6, + }); + + table[ISA_OP_STX_ZP as usize] = Some(OpInfo { + operation: Operation::STX, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 3, + }); + table[ISA_OP_STX_ZPY as usize] = Some(OpInfo { + operation: Operation::STX, + mode: AddressMode::ZeroPageY, + length: 2, + cycles: 4, + }); + table[ISA_OP_STX_ABS as usize] = Some(OpInfo { + operation: Operation::STX, + mode: AddressMode::Absolute, + length: 3, + cycles: 4, + }); + + table[ISA_OP_STY_ZP as usize] = Some(OpInfo { + operation: Operation::STY, + mode: AddressMode::ZeroPage, + length: 2, + cycles: 3, + }); + table[ISA_OP_STY_ZPX as usize] = Some(OpInfo { + operation: Operation::STY, + mode: AddressMode::ZeroPageX, + length: 2, + cycles: 4, + }); + table[ISA_OP_STY_ABS as usize] = Some(OpInfo { + operation: Operation::STY, + mode: AddressMode::Absolute, + length: 3, + cycles: 4, + }); + + table[ISA_OP_TAX as usize] = Some(OpInfo { + operation: Operation::TAX, + mode: AddressMode::Implied, + length: 1, + cycles: 2, + }); + table[ISA_OP_TAY as usize] = Some(OpInfo { + operation: TAY, + mode: AddressMode::Implied, + length: 1, + cycles: 2, + }); + table[ISA_OP_TSX as usize] = Some(OpInfo { + operation: TSX, + mode: AddressMode::Implied, + length: 1, + cycles: 2, + }); + table[ISA_OP_TXA as usize] = Some(OpInfo { + operation: Operation::TXA, + mode: AddressMode::Implied, + length: 1, + cycles: 2, + }); + table[ISA_OP_TXS as usize] = Some(OpInfo { + operation: Operation::TXS, + mode: AddressMode::Implied, + length: 1, + cycles: 2, + }); + table[ISA_OP_TYA as usize] = Some(OpInfo { + operation: TYA, + mode: AddressMode::Implied, + length: 1, + cycles: 2, + }); + + table +}; diff --git a/core/src/isa/decoder.rs b/core/src/isa/decoder.rs deleted file mode 100644 index 3706602..0000000 --- a/core/src/isa/decoder.rs +++ /dev/null @@ -1,76 +0,0 @@ -use crate::address_mode::AddressMode::*; -use crate::instruction::Instruction; -use crate::instruction::Instruction::*; - -pub struct Decoder {} - - -impl Decoder { - /// decode - /// - /// Returns the decoded instruction or a NOP. - /// NOP will be returned when an instruction without a valid parameter - /// and more data is required to decode. - pub fn decode(decode_from: Vec) -> Instruction { - Instruction::from_bytes(decode_from) - } -} - -#[cfg(test)] -mod test { - use crate::constants::constants_isa_op::{ISA_OP_ADC_ABS, ISA_OP_ADC_ABSX, ISA_OP_ADC_ABSY, ISA_OP_ADC_I, ISA_OP_ADC_INDX, ISA_OP_ADC_INDY, ISA_OP_ADC_Z, ISA_OP_ADC_ZX, ISA_OP_AND_ABS, ISA_OP_AND_I, ISA_OP_AND_Z, ISA_OP_AND_ZX, ISA_OP_ASL_A, ISA_OP_ASL_ABS, ISA_OP_ASL_ABSX, ISA_OP_ASL_Z, ISA_OP_ASL_ZX, ISA_OP_BCC, ISA_OP_BEQ, ISA_OP_BIT_ABS, ISA_OP_BIT_ZP, ISA_OP_BMI, ISA_OP_BNE, ISA_OP_BPL, ISA_OP_BRK, ISA_OP_BVC, ISA_OP_BVS}; - use super::*; - - - #[test] - fn valid_decodes() { - let params = vec![ - (vec![ISA_OP_ADC_I, 0xab], ADC(Immediate(0xab))), - (vec![ISA_OP_ADC_Z, 0xab], ADC(ZeroPage(0xab))), - (vec![ISA_OP_ADC_ZX, 0xab], ADC(ZeroPageX(0xab))), - (vec![ISA_OP_ADC_ABS, 0xab, 0xcd], ADC(Absolute(0xcdab))), - (vec![ISA_OP_ADC_ABSX, 0xcd, 0xab], ADC(AbsoluteX(0xabcd))), - (vec![ISA_OP_ADC_ABSY, 0xcd, 0xab], ADC(AbsoluteY(0xabcd))), - (vec![ISA_OP_ADC_INDX, 0xab], ADC(IndirectX(0xab))), - (vec![ISA_OP_ADC_INDY, 0xcd], ADC(IndirectY(0xcd))), - - (vec![ISA_OP_AND_I, 0xab], AND(Immediate(0xab))), - (vec![ISA_OP_AND_Z, 0xab], AND(ZeroPage(0xab))), - (vec![ISA_OP_AND_ZX, 0xab], AND(ZeroPageX(0xab))), - (vec![ISA_OP_AND_ABS, 0xcd, 0xab], AND(Absolute(0xabcd))), - - (vec![ISA_OP_ASL_A], ASL(Accumulator)), - (vec![ISA_OP_ASL_Z, 0xab], ASL(ZeroPage(0xab))), - (vec![ISA_OP_ASL_ZX, 0xab], ASL(ZeroPageX(0xab))), - (vec![ISA_OP_ASL_ABS, 0xab, 0xcd], ASL(Absolute(0xcdab))), - (vec![ISA_OP_ASL_ABSX, 0xab, 0xcd], ASL(AbsoluteX(0xcdab))), - - (vec![ISA_OP_BCC, 0xab], BCC(Immediate(0xab))), - - (vec![ISA_OP_BEQ, 0xab], BEQ(Immediate(0xab))), - - (vec![ISA_OP_BIT_ZP, 0xab], BIT(ZeroPage(0xab))), - (vec![ISA_OP_BIT_ABS, 0xab, 0xcd], BIT(Absolute(0xcdab))), - - (vec![ISA_OP_BMI, 0xab], BMI(Immediate(0xab))), - (vec![ISA_OP_BNE, 0xab], BNE(Immediate(0xab))), - (vec![ISA_OP_BPL, 0xab], BPL(Immediate(0xab))), - (vec![ISA_OP_BVC, 0xab], BVC(Immediate(0xab))), - (vec![ISA_OP_BVS, 0xab], BVS(Immediate(0xab))), - - (vec![ISA_OP_BRK], BRK), - - - - ]; - - for (bytes, instruction) in params { - println!("Expecting {:?} to be {:?}", bytes, instruction); - - assert_eq!( - Decoder::decode(bytes), - instruction - ) - } - } -} \ No newline at end of file diff --git a/core/src/isa/encode.rs b/core/src/isa/encode.rs deleted file mode 100644 index e8b930b..0000000 --- a/core/src/isa/encode.rs +++ /dev/null @@ -1,129 +0,0 @@ -use crate::address_mode::AddressMode::*; -use crate::constants::constants_isa_op::ISA_OP_BCC; -use crate::instruction::Instruction; -use crate::instruction::Instruction::*; - -pub struct Encoder {} - -impl Encoder { - pub fn encode(to_encode: Instruction) -> Vec { - match to_encode { - // ADC(_) => {} - // AND(_) => {} - // ASL(_) => {} - BCC(mode) => { - match mode { - Immediate(address)=> { - vec![ISA_OP_BCC, address] - } - _ => NOP.to_bytes() - } - } - // BCS(_) => {} - // BEQ(_) => {} - // BIT(_) => {} - // BMI(_) => {} - // BNE(_) => {} - // BPL(_) => {} - // BRK => {} - // BVC(_) => {} - // BVS(_) => {} - // CLC => {} - // CLD => {} - // CLI => {} - // CLV => {} - // CMP(_) => {} - // CPX(_) => {} - // CPY(_) => {} - // DEC(_) => {} - // DEX => {} - // DEY => {} - // EOR(_) => {} - // INC(_) => {} - // INX => {} - // INY => {} - // JMP(_) => {} - // JSR(_) => {} - // LDA(_) => {} - // LDX(_) => {} - // LDY(_) => {} - // LSR(_) => {} - // NOP => {} - // ORA(_) => {} - // PHA => {} - // PHP => {} - // PLA => {} - // PLP => {} - // ROL(_) => {} - // ROR(_) => {} - // RTI => {} - // RTS => {} - // SBC(_) => {} - // SEC => {} - // SED => {} - // SEI => {} - // STA(_) => {} - // STX(_) => {} - // STY(_) => {} - // TAX => {} - // TAY => {} - // TSX => {} - // TXA => {} - // TXS => {} - // TYA => {} - _ => NOP.to_bytes() - } - } -} - -#[cfg(test)] -mod test { - use crate::constants::constants_isa_op::{ISA_OP_ADC_ABS, ISA_OP_ADC_ABSX, ISA_OP_ADC_ABSY, ISA_OP_ADC_I, ISA_OP_ADC_INDX, ISA_OP_ADC_INDY, ISA_OP_ADC_Z, ISA_OP_ADC_ZX, ISA_OP_AND_ABS, ISA_OP_AND_I, ISA_OP_AND_Z, ISA_OP_AND_ZX, ISA_OP_ASL_A, ISA_OP_ASL_ABS, ISA_OP_ASL_ABSX, ISA_OP_ASL_Z, ISA_OP_ASL_ZX, ISA_OP_BEQ, ISA_OP_BIT_ABS, ISA_OP_BIT_ZP, ISA_OP_BMI, ISA_OP_BNE, ISA_OP_BPL, ISA_OP_BRK, ISA_OP_BVC, ISA_OP_BVS}; - use super::*; - - #[test] - fn adc_decode() { - let params = vec![ - (vec![ISA_OP_ADC_I, 0xab], ADC(Immediate(0xab))), - (vec![ISA_OP_ADC_Z, 0xab], ADC(ZeroPage(0xab))), - (vec![ISA_OP_ADC_ZX, 0xab], ADC(ZeroPageX(0xab))), - (vec![ISA_OP_ADC_ABS, 0xab, 0xcd], ADC(Absolute(0xcdab))), - (vec![ISA_OP_ADC_ABSX, 0xcd, 0xab], ADC(AbsoluteX(0xabcd))), - (vec![ISA_OP_ADC_ABSY, 0xcd, 0xab], ADC(AbsoluteY(0xabcd))), - (vec![ISA_OP_ADC_INDX, 0xab], ADC(IndirectX(0xab))), - (vec![ISA_OP_ADC_INDY, 0xcd], ADC(IndirectY(0xcd))), - - (vec![ISA_OP_AND_I, 0xab], AND(Immediate(0xab))), - (vec![ISA_OP_AND_Z, 0xab], AND(ZeroPage(0xab))), - (vec![ISA_OP_AND_ZX, 0xab], AND(ZeroPageX(0xab))), - (vec![ISA_OP_AND_ABS, 0xcd, 0xab], AND(Absolute(0xabcd))), - - (vec![ISA_OP_ASL_A], ASL(Accumulator)), - (vec![ISA_OP_ASL_Z, 0xab], ASL(ZeroPage(0xab))), - (vec![ISA_OP_ASL_ZX, 0xab], ASL(ZeroPageX(0xab))), - (vec![ISA_OP_ASL_ABS, 0xab, 0xcd], ASL(Absolute(0xcdab))), - (vec![ISA_OP_ASL_ABSX, 0xab, 0xcd], ASL(AbsoluteX(0xcdab))), - - (vec![ISA_OP_BCC, 0xab], BCC(Immediate(0xab))), - - (vec![ISA_OP_BEQ, 0xab], BEQ(Immediate(0xab))), - - (vec![ISA_OP_BIT_ZP, 0xab], BIT(ZeroPage(0xab))), - (vec![ISA_OP_BIT_ABS, 0xab, 0xcd], BIT(Absolute(0xcdab))), - - (vec![ISA_OP_BMI, 0xab], BMI(Immediate(0xab))), - (vec![ISA_OP_BNE, 0xab], BNE(Immediate(0xab))), - (vec![ISA_OP_BPL, 0xab], BPL(Immediate(0xab))), - (vec![ISA_OP_BVC, 0xab], BVC(Immediate(0xab))), - (vec![ISA_OP_BVS, 0xab], BVS(Immediate(0xab))), - - (vec![ISA_OP_BRK], BRK), - - ]; - - // for (bytes, instruction) in params { - // let encoded = Encoder::encode(bytes); - // assert_eq!(encoded, instruction.into()); - // } - } -} diff --git a/core/src/isa/microcode_steps.rs b/core/src/isa/microcode_steps.rs deleted file mode 100644 index 2c27d5b..0000000 --- a/core/src/isa/microcode_steps.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::mos6502flags::Mos6502Flag; - -pub enum MicrocodeStep { - ReadRegisterA, - ReadRegisterX, - ReadRegisterY, - ReadFlag(Mos6502Flag), - WriteRegisterA, - WriteRegisterX, - WriteRegisterY, - WriteFlag(Mos6502Flag, bool), - ReadMemory(u16), - WriteMemory(u16, u8), - ALUAdd(u8, u8), - ALUSub(u8, u8), - ALUAddC(u8, u8, bool), - ALUSubC(u8, u8, bool), -} diff --git a/core/src/isa/mod.rs b/core/src/isa/mod.rs deleted file mode 100644 index 66ddc09..0000000 --- a/core/src/isa/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod encode; -pub mod decoder; -pub mod microcode_steps; diff --git a/core/src/lib.rs b/core/src/lib.rs index 8537419..4331b55 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -2,5 +2,8 @@ pub mod address_mode; pub mod mos6502cpu; pub mod instruction; pub mod mos6502flags; -pub mod isa; pub mod constants; +mod operation; +mod op_info; +mod operand; +mod instruction_table; diff --git a/core/src/op_info.rs b/core/src/op_info.rs new file mode 100644 index 0000000..10f80f8 --- /dev/null +++ b/core/src/op_info.rs @@ -0,0 +1,10 @@ +use crate::address_mode::AddressMode; +use crate::operation::Operation; + +#[derive(Debug, Copy, Clone)] +pub struct OpInfo { + pub operation: Operation, + pub mode: AddressMode, + pub length: u8, + pub cycles: u8, +} diff --git a/core/src/operand.rs b/core/src/operand.rs new file mode 100644 index 0000000..106bc47 --- /dev/null +++ b/core/src/operand.rs @@ -0,0 +1,6 @@ +#[derive(Debug, PartialEq)] +pub enum Operand { + None, + Byte(u8), + Word(u16), +} diff --git a/core/src/instruction/mod.rs b/core/src/operation.rs similarity index 75% rename from core/src/instruction/mod.rs rename to core/src/operation.rs index 716ee27..49d43ed 100644 --- a/core/src/instruction/mod.rs +++ b/core/src/operation.rs @@ -1,16 +1,6 @@ -use crate::address_mode::AddressMode; -use crate::address_mode::AddressMode::*; -use crate::instruction::Instruction::*; -use crate::mos6502flags::Mos6502Flag::*; -mod from_bytes; -mod to_bytes; -mod execute; -mod stub; -mod to_string; - -#[derive(PartialEq, Debug)] -pub enum Instruction { +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum Operation { /// ADC – Add with Carry /// A,Z,C,N = A+M+C /// @@ -35,7 +25,7 @@ pub enum Instruction { /// Absolute,Y $79 3 4 (+1 if page crossed) /// (Indirect,X) $61 2 6 /// (Indirect),Y $71 2 5 (+1 if page crossed) - ADC(AddressMode), + ADC, /// AND /// A,Z,N = A&M /// @@ -61,7 +51,7 @@ pub enum Instruction { /// (Indirect,X) $21 2 6 /// (Indirect),Y $31 2 5 (+1 if page crossed) /// - AND(AddressMode), + AND, /// ASL /// A,Z,C,N = M*2 or M,Z,C,N = M*2 /// @@ -83,7 +73,7 @@ pub enum Instruction { /// ZeroPage,X $16 2 6 /// Absolute $0E 3 6 /// Absolute,X $1E 3 7 - ASL(AddressMode), + ASL, /// BCC – Branch if Carry Clear /// If the carry flag is clear then add the relative displacement to the program counter to cause a branch to a new location. /// @@ -100,7 +90,8 @@ pub enum Instruction { /// Relative $90 2 2 (+1 if branch succeeds /// /// +2 if to a new page) - BCC(AddressMode), + + BCC, /// BCS – Branch if Carry Set /// If the carry flag is set then add the relative displacement to the program counter to cause a branch to a new location. /// @@ -118,7 +109,8 @@ pub enum Instruction { /// Relative $B0 2 2 (+1 if branch succeeds /// /// +2 if to a new page) - BCS(AddressMode), + + BCS, /// BEQ – Branch if Equal /// If the zero flag is set then add the relative displacement to the program counter to cause a branch to a new location. /// @@ -135,7 +127,7 @@ pub enum Instruction { /// Relative $F0 2 2 (+1 if branch succeeds /// /// +2 if to a new page) - BEQ(AddressMode), + BEQ, /// BIT – Bit Test /// A & M, N = M7, V = M6 /// @@ -153,7 +145,7 @@ pub enum Instruction { /// Addressing Mode Opcode Bytes Cycles /// ZeroPage $24 2 3 /// Absolute $2C 3 4 - BIT(AddressMode), + BIT, /// BMI – Branch if Minus /// If the negative flag is set then add the relative displacement to the program counter to cause a branch to a new location. /// @@ -170,7 +162,7 @@ pub enum Instruction { /// Relative $30 2 2 (+1 if branch succeeds /// /// +2 if to a new page) - BMI(AddressMode), + BMI, /// BNE – Branch if Not Equal /// If the zero flag is clear then add the relative displacement to the program counter to cause a branch to a new location. /// @@ -187,7 +179,7 @@ pub enum Instruction { /// Relative $D0 2 2 (+1 if branch succeeds /// /// +2 if to a new page) - BNE(AddressMode), + BNE, /// BPL – Branch if Positive /// If the negative flag is clear then add the relative displacement to the program counter to cause a branch to a new location. /// @@ -204,7 +196,7 @@ pub enum Instruction { /// Relative $10 2 2 (+1 if branch succeeds /// /// +2 if to a new page) - BPL(AddressMode), + BPL, /// BRK – Force Interrupt /// The BRK instruction forces the generation of an interrupt request. The program counter and processor status are pushed on the stack then the IRQ interrupt vector at $FFFE/F is loaded into the PC and the break flag in the status set to one. /// @@ -235,7 +227,7 @@ pub enum Instruction { /// Relative $50 2 2 (+1 if branch succeeds /// /// +2 if to a new page) - BVC(AddressMode), + BVC, /// BVS – Branch if Overflow Set /// If the overflow flag is set then add the relative displacement to the program counter to cause a branch to a new location. /// @@ -252,7 +244,7 @@ pub enum Instruction { /// Relative $70 2 2 (+1 if branch succeeds /// /// +2 if to a new page) - BVS(AddressMode), + BVS, /// CLC – Clear Carry Flag /// C = 0 /// @@ -337,7 +329,7 @@ pub enum Instruction { /// Absolute,Y $D9 3 4 (+1 if page crossed) /// (Indirect,X) $C1 2 6 /// (Indirect),Y $D1 2 5 (+1 if page crossed) - CMP(AddressMode), + CMP, /// CPX – Compare X Register /// Z,C,N = X-M /// @@ -356,7 +348,7 @@ pub enum Instruction { /// Immediate $E0 2 2 /// Zero Page $E4 2 3 /// Absolute $EC 3 4 - CPX(AddressMode), + CPX, /// CPY – Compare Y Register /// Z,C,N = Y-M /// @@ -375,7 +367,7 @@ pub enum Instruction { /// Immediate $C0 2 2 /// Zero Page $C4 2 3 /// Absolute $CC 3 4 - CPY(AddressMode), + CPY, /// DEC – Decrement Memory /// M,Z,N = M-1 /// @@ -395,7 +387,7 @@ pub enum Instruction { /// Zero Page,X $D6 2 6 /// Absolute $CE 3 6 /// Absolute,X $DE 3 7 - DEC(AddressMode), + DEC, /// DEX – Decrement X Register /// X,Z,N = X-1 /// @@ -453,7 +445,7 @@ pub enum Instruction { /// Absolute,Y $59 3 4 (+1 if page crossed) /// (Indirect,X) $41 2 6 /// (Indirect),Y $51 2 5 (+1 if page crossed) - EOR(AddressMode), + EOR, /// INC – Increment Memory /// M,Z,N = M+1 /// @@ -473,7 +465,7 @@ pub enum Instruction { /// Zero Page,X $F6 2 6 /// Absolute $EE 3 6 /// Absolute,X $FE 3 7 - INC(AddressMode), + INC, /// INX – Increment X Register /// X,Z,N = X+1 /// @@ -523,7 +515,7 @@ pub enum Instruction { /// Addressing Mode Opcode Bytes Cycles /// Absolute $4C 3 3 /// Indirect $6C 3 5 - JMP(AddressMode), + JMP, /// JSR – Jump to Subroutine /// The JSR instruction pushes the address (minus one) of the return point on to the stack and then sets the program counter to the target memory address. /// @@ -538,7 +530,7 @@ pub enum Instruction { /// N Negative Flag Not affected /// Addressing Mode Opcode Bytes Cycles /// Absolute $20 3 6 - JSR(AddressMode), + JSR, /// LDA – Load Accumulator /// A,Z,N = M /// @@ -560,7 +552,7 @@ pub enum Instruction { /// Absolute,Y $B9 3 4 (+1 if page crossed) /// (Indirect,X) $A1 2 6 /// (Indirect),Y $B1 2 5 (+1 if page crossed) - LDA(AddressMode), + LDA, /// LDX – Load X Register /// X,Z,N = M /// @@ -579,7 +571,7 @@ pub enum Instruction { /// Zero Page,Y $B6 2 4 /// Absolute $AE 3 4 /// Absolute,Y $BE 3 4 (+1 if page crossed) - LDX(AddressMode), + LDX, /// LDY – Load Y Register /// Y,Z,N = M /// @@ -598,7 +590,7 @@ pub enum Instruction { /// Zero Page,X $B4 2 4 /// Absolute $AC 3 4 /// Absolute,X $BC 3 4 (+1 if page crossed) - LDY(AddressMode), + LDY, /// LSR – Logical Shift Right /// A,C,Z,N = A/2 or M,C,Z,N = M/2 /// @@ -619,7 +611,7 @@ pub enum Instruction { /// ZeroPage,X $56 2 6 /// Absolute $4E 3 6 /// Absolute,X $5E 3 7 - LSR(AddressMode), + LSR, /// NOP – No Operation /// The NOP instruction causes no changes to the processor other than the normal incrementing of the program counter to the next instruction. /// @@ -658,7 +650,7 @@ pub enum Instruction { /// Absolute,Y $19 3 4 (+1 if page crossed) /// (Indirect,X) $01 2 6 /// (Indirect),Y $11 2 5 (+1 if page crossed) - ORA(AddressMode), + ORA, /// PHA – Push Accumulator /// Pushes a copy of the accumulator on to the stack. /// @@ -735,7 +727,7 @@ pub enum Instruction { /// ZeroPage,X $36 2 6 /// Absolute $2E 3 6 /// Absolute,X $3E 3 7 - ROL(AddressMode), + ROL, /// ROR – Rotate Right /// Move each of the bits in either A or M one place to the right. Bit 7 is filled with the current value of the carry flag while the old bit 0 becomes the new carry flag value. /// @@ -754,7 +746,7 @@ pub enum Instruction { /// ZeroPage,X $76 2 6 /// Absolute $6E 3 6 /// Absolute,X $7E 3 7 - ROR(AddressMode), + ROR, /// RTI – Return from Interrupt /// The RTI instruction is used at the end of an interrupt processing routine. It pulls the processor flags from the stack followed by the program counter. /// @@ -808,7 +800,7 @@ pub enum Instruction { /// Absolute,Y $F9 3 4 (+1 if page crossed) /// (Indirect,X) $E1 2 6 /// (Indirect),Y $F1 2 5 (+1 if page crossed) - SBC(AddressMode), + SBC, /// SEC – Set Carry Flag /// C = 1 /// @@ -876,7 +868,7 @@ pub enum Instruction { /// Absolute,Y $99 3 5 /// (Indirect,X) $81 2 6 /// (Indirect),Y $91 2 6 - STA(AddressMode), + STA, /// STX – Store X Register /// M = X /// @@ -895,7 +887,7 @@ pub enum Instruction { /// Zero Page $86 2 3 /// Zero Page,Y $96 2 4 /// Absolute $8E 3 4 - STX(AddressMode), + STX, /// STY – Store Y Register /// M = Y /// @@ -914,7 +906,7 @@ pub enum Instruction { /// Zero Page $84 2 3 /// Zero Page,X $94 2 4 /// Absolute $8C 3 4 - STY(AddressMode), + STY, /// TAX – Transfer Accumulator to X /// X = A /// @@ -1018,199 +1010,3 @@ pub enum Instruction { /// Implied $98 1 2 TYA, } - -#[cfg(test)] -mod test { - use crate::address_mode::AddressMode::*; - use crate::instruction::Instruction::*; - use super::*; - - #[test] - fn to_string_to_bytes_from_bytes() { - let params = vec![ - (ADC(Immediate(0x01)), "ADC #$01", vec![0x69, 0x01]), - (ADC(ZeroPage(0x01)), "ADC $01", vec![0x65, 0x01]), - (ADC(ZeroPageX(0x01)), "ADC $01,X", vec![0x75, 0x01]), - (ADC(Absolute(0xabcd)), "ADC $abcd", vec![0x6d, 0xcd, 0xab]), - (ADC(AbsoluteX(0xabcd)), "ADC $abcd,X", vec![0x7d, 0xcd, 0xab]), - (ADC(AbsoluteY(0xabcd)), "ADC $abcd,Y", vec![0x79, 0xcd, 0xab]), - (ADC(IndirectX(0xab)), "ADC ($ab,X)", vec![0x61, 0xab]), - (ADC(IndirectY(0xab)), "ADC ($ab),Y", vec![0x71, 0xab]), - (AND(Immediate(0x01)), "AND #$01", vec![0x29, 0x01]), - (AND(ZeroPage(0x01)), "AND $01", vec![0x25, 0x01]), - (AND(ZeroPageX(0x01)), "AND $01,X", vec![0x35, 0x01]), - (AND(Absolute(0xabcd)), "AND $abcd", vec![0x2d, 0xcd, 0xab]), - (AND(AbsoluteX(0xabcd)), "AND $abcd,X", vec![0x3d, 0xcd, 0xab]), - (AND(AbsoluteY(0xabcd)), "AND $abcd,Y", vec![0x39, 0xcd, 0xab]), - (AND(IndirectX(0xab)), "AND ($ab,X)", vec![0x21, 0xab]), - (AND(IndirectY(0xab)), "AND ($ab),Y", vec![0x31, 0xab]), - (ASL(Accumulator), "ASL A", vec![0x0a]), - (ASL(ZeroPage(0xab)), "ASL $ab", vec![0x06, 0xab]), - (ASL(ZeroPageX(0xab)), "ASL $ab,X", vec![0x16, 0xab]), - (ASL(Absolute(0xabcd)), "ASL $abcd", vec![0x0e, 0xcd, 0xab]), - (ASL(AbsoluteX(0xabcd)), "ASL $abcd,X", vec![0x1e, 0xcd, 0xab]), - (BCC(Immediate(0xab)), "BCC #$ab", vec![0x90, 0xab]), - (BCS(Immediate(0xab)), "BCS #$ab", vec![0xb0, 0xab]), - (BEQ(Immediate(0xab)), "BEQ #$ab", vec![0xf0, 0xab]), - (BIT(ZeroPage(0xab)), "BIT $ab", vec![0x24, 0xab]), - (BIT(Absolute(0xabcd)), "BIT $abcd", vec![0x2c, 0xcd, 0xab]), - (BMI(Immediate(0xab)), "BMI #$ab", vec![0x30, 0xab]), - (BNE(Immediate(0xab)), "BNE #$ab", vec![0xd0, 0xab]), - (BPL(Immediate(0xab)), "BPL #$ab", vec![0x10, 0xab]), - (BVC(Immediate(0xab)), "BVC #$ab", vec![0x50, 0xab]), - (BVS(Immediate(0xab)), "BVS #$ab", vec![0x70, 0xab]), - (CLC, "CLC", vec![0x18]), - (CLD, "CLD", vec![0xd8]), - (CLV, "CLV", vec![0x8b]), - (CLI, "CLI", vec![0x85]), - (CMP(Immediate(0xab)), "CMP #$ab", vec![0xc9, 0xab]), - (CMP(ZeroPage(0xab)), "CMP $ab", vec![0xc5, 0xab]), - (CMP(ZeroPageX(0xab)), "CMP $ab,X", vec![0xd5, 0xab]), - (CMP(Absolute(0xabcd)), "CMP $abcd", vec![0xcd, 0xcd, 0xab]), - (CMP(AbsoluteX(0xabcd)), "CMP $abcd,X", vec![0xdd, 0xcd, 0xab]), - (CMP(IndirectX(0xab)), "CMP ($ab,X)", vec![0xc1, 0xab]), - (CMP(IndirectY(0xab)), "CMP ($ab),Y", vec![0xd1, 0xab]), - (CPX(Immediate(0xab)), "CPX #$ab", vec![0xe0, 0xab]), - (CPX(ZeroPage(0xab)), "CPX $ab", vec![0xe4, 0xab]), - (CPX(Absolute(0xabcd)), "CPX $abcd", vec![0xec, 0xcd, 0xab]), - (CPY(Immediate(0xab)), "CPY #$ab", vec![0xc0, 0xab]), - (CPY(Immediate(0xab)), "CPY #$ab", vec![0xc0, 0xab]), - (CPY(ZeroPage(0xab)), "CPY $ab", vec![0xc4, 0xab]), - (CPY(Absolute(0xabcd)), "CPY $abcd", vec![0xcc, 0xcd, 0xab]), - (DEC(ZeroPage(0xab)), "DEC $ab", vec![0xc6, 0xab]), - (DEC(ZeroPageX(0xab)), "DEC $ab,X", vec![0xd6, 0xab]), - (DEC(Absolute(0xabcd)), "DEC $abcd", vec![0xce, 0xcd, 0xab]), -// (DEC(AbsoluteX(0xabcd)), "DEC $abcd,X", vec![0xde, 0xcd, 0xab]), - (DEX, "DEX", vec![0xca]), - (DEY, "DEY", vec![0x88]), - (EOR(Immediate(0xab)), "EOR #$ab", vec![0x49, 0xab]), - (EOR(ZeroPage(0xab)), "EOR $ab", vec![0x45, 0xab]), - (EOR(ZeroPageX(0xab)), "EOR $ab,X", vec![0x55, 0xab]), - (EOR(Absolute(0xabcd)), "EOR $abcd", vec![0x4d, 0xcd, 0xab]), - (EOR(AbsoluteX(0xabcd)), "EOR $abcd,X", vec![0x5d, 0xcd, 0xab]), - (EOR(IndirectX(0xab)), "EOR ($ab,X)", vec![0x41, 0xab]), - (EOR(IndirectY(0xab)), "EOR ($ab),Y", vec![0x51, 0xab]), - (INC(ZeroPage(0xab)), "INC $ab", vec![0xe6, 0xab]), - (INC(ZeroPageX(0xab)), "INC $ab,X", vec![0xf6, 0xab]), - (INC(Absolute(0xabcd)), "INC $abcd", vec![0xee, 0xcd, 0xab]), - (INC(AbsoluteX(0xabcd)), "INC $abcd,X", vec![0xfe, 0xcd, 0xab]), - (INX, "INX", vec![0xe8]), - (INY, "INY", vec![0xc8]), - (JMP(Absolute(0xabcd)), "JMP $abcd", vec![0x4c, 0xcd, 0xab]), - (JMP(IndirectX(0xab)), "JMP ($ab,X)", vec![0x6c, 0xab]), - (JSR(Immediate(0xab)), "JSR #$ab", vec![0x20, 0xab]), - (LDA(Immediate(0xab)), "LDA #$ab", vec![0xa9, 0xab]), - (LDA(ZeroPage(0xab)), "LDA $ab", vec![0xa5, 0xab]), - (LDA(ZeroPageX(0xab)), "LDA $ab,X", vec![0xb5, 0xab]), - (LDA(Absolute(0xabcd)), "LDA $abcd", vec![0xad, 0xcd, 0xab]), - (LDA(AbsoluteX(0xabcd)), "LDA $abcd,X", vec![0xbd, 0xcd, 0xab]), - (LDA(AbsoluteY(0xabcd)), "LDA $abcd,Y", vec![0xb9, 0xcd, 0xab]), - (LDA(IndirectX(0xab)), "LDA ($ab,X)", vec![0xa1, 0xab]), - (LDA(IndirectY(0xab)), "LDA ($ab),Y", vec![0xb1, 0xab]), - (LDX(Immediate(0xab)), "LDX #$ab", vec![0xa2, 0xab]), - (LDX(ZeroPage(0xab)), "LDX $ab", vec![0xa6, 0xab]), - (LDX(ZeroPageY(0xab)), "LDX $ab,Y", vec![0x86, 0xab]), - (LDX(Absolute(0xabcd)), "LDX $abcd", vec![0xae, 0xcd, 0xab]), - (LDX(AbsoluteY(0xabcd)), "LDX $abcd,Y", vec![0xbe, 0xcd, 0xab]), - (LDY(Immediate(0xab)), "LDY #$ab", vec![0xa0, 0xab]), - (LDY(ZeroPage(0xab)), "LDY $ab", vec![0xa4, 0xab]), - (LDY(ZeroPageX(0xab)), "LDY $ab,X", vec![0x84, 0xab]), - (LDY(Absolute(0xabcd)), "LDY $abcd", vec![0xac, 0xcd, 0xab]), - (LDY(AbsoluteX(0xabcd)), "LDY $abcd,X", vec![0xbc, 0xcd, 0xab]), - (LSR(Accumulator), "LSR A", vec![0x4a]), - (LSR(ZeroPage(0xab)), "LSR $ab", vec![0x46, 0xab]), - (LSR(ZeroPageX(0xab)), "LSR $ab,X", vec![0x56, 0xab]), - (LSR(Absolute(0xabcd)), "LSR $abcd", vec![0x4e, 0xcd, 0xab]), - (LSR(AbsoluteX(0xabcd)), "LSR $abcd,X", vec![0x5e, 0xcd, 0xab]), - // Nop nop nop. - (NOP, "NOP", vec![0xea]), - (ORA(Immediate(0xab)), "ORA #$ab", vec![0x09, 0xab]), - (ORA(ZeroPage(0xab)), "ORA $ab", vec![0x05, 0xab]), - (ORA(ZeroPageX(0xab)), "ORA $ab,X", vec![0x15, 0xab]), - (ORA(Absolute(0xabcd)), "ORA $abcd", vec![0x0d, 0xcd, 0xab]), - (ORA(AbsoluteX(0xabcd)), "ORA $abcd,X", vec![0x1d, 0xcd, 0xab]), - (ORA(AbsoluteY(0xabcd)), "ORA $abcd,Y", vec![0x19, 0xcd, 0xab]), - (ORA(IndirectX(0xab)), "ORA ($ab,X)", vec![0x01, 0xab]), - (ORA(IndirectY(0xab)), "ORA ($ab),Y", vec![0x11, 0xab]), - (PHA, "PHA", vec![0x48]), - (PHP, "PHP", vec![0x08]), - (PLA, "PLA", vec![0x68]), - (PLP, "PLP", vec![0x28]), - (ROL(Accumulator), "ROL A", vec![0x2a]), - (ROL(ZeroPage(0xab)), "ROL $ab", vec![0x26, 0xab]), - (ROL(ZeroPageX(0xab)), "ROL $ab,X", vec![0x36, 0xab]), - (ROL(Absolute(0xabcd)), "ROL $abcd", vec![0x2e, 0xcd, 0xab]), - (ROL(AbsoluteX(0xabcd)), "ROL $abcd,X", vec![0x3e, 0xcd, 0xab]), - (ROR(Accumulator), "ROR A", vec![0x6a]), - (ROR(ZeroPage(0xab)), "ROR $ab", vec![0x66, 0xab]), - (ROR(ZeroPageX(0xab)), "ROR $ab,X", vec![0x76, 0xab]), - (ROR(Absolute(0xabcd)), "ROR $abcd", vec![0x6e, 0xcd, 0xab]), - (ROR(AbsoluteX(0xabcd)), "ROR $abcd,X", vec![0x7e, 0xcd, 0xab]), - - (RTI, "RTI", vec![0x40]), - (RTS, "RTS", vec![0x60]), - (SBC(Immediate(0xab)), "SBC #$ab", vec![0xe9, 0xcd, 0xab]), - (SBC(ZeroPage(0xab)), "SBC $ab", vec![0xe5, 0xab]), - (SBC(ZeroPageX(0xab)), "SBC $ab,X", vec![0xf5, 0xab]), - (SBC(Absolute(0xabcd)), "SBC $abcd", vec![0xed, 0xcd, 0xab]), - (SBC(AbsoluteX(0xabcd)), "SBC $abcd,X", vec![0xfd, 0xcd, 0xab]), - (SBC(AbsoluteY(0xabcd)), "SBC $abcd,Y", vec![0xf9, 0xcd, 0xab]), - (SBC(IndirectX(0xab)), "SBC ($ab,X)", vec![0xe1, 0xab]), - (SBC(IndirectY(0xab)), "SBC ($ab),Y", vec![0xf1, 0xab]), - - (SEC, "SEC", vec![0x38]), - (SED, "SED", vec![0xf8]), - (SEI, "SEI", vec![0x78]), - - (STA(ZeroPage(0xab)), "STA $ab", vec![0x85, 0xab]), - (STA(ZeroPageX(0xab)), "STA $ab,X", vec![0x95, 0xab]), - (STA(Absolute(0xabcd)), "STA $abcd", vec![0x8d, 0xcd, 0xab]), - (STA(AbsoluteX(0xabcd)), "STA $abcd,X", vec![0x9d, 0xcd, 0xab]), - (STA(AbsoluteY(0xabcd)), "STA $abcd,Y", vec![0x99, 0xcd, 0xab]), - (STA(IndirectX(0xab)), "STA ($ab,X)", vec![0x81, 0xab]), - (STA(IndirectY(0xab)), "STA ($ab),Y", vec![0x91, 0xab]), - - (STX(ZeroPage(0xab)), "STX $ab", vec![0x86, 0xab]), - (STX(ZeroPageX(0xab)), "STX $ab,X", vec![0x96, 0xab]), - (STX(Absolute(0xabcd)), "STX $abcd", vec![0x8e, 0xcd, 0xab]), - - (STY(ZeroPage(0xab)), "STY $ab", vec![0x84, 0xab]), - (STY(ZeroPageX(0xab)), "STY $ab,X", vec![0x94, 0xab]), - (STY(Absolute(0xabcd)), "STY $abcd", vec![0x8c, 0xcd, 0xab]), - - (TAX, "TAX", vec![0xaa]), - (TAY, "TAY", vec![0xa8]), - (TSX, "TSX", vec![0xba]), - (TXA, "TXA", vec![0x8a]), - (TXS, "TXS", vec![0x9a]), - (TYA, "TYA", vec![0x98]) - ]; - - for (instruction, string, bytes) in params { - - println!("COMPARE OF [{:?}] to {:?} and [{}]", instruction, bytes, string); - // from instruction to string - assert_eq!( - instruction.to_string(), - string - ); - print!("to string passed."); -/* - // from instruction to bytes - assert_eq!( - instruction.to_bytes(), - bytes - ); - print!("to bytes passed."); - - // from bytes to instruction - assert_eq!( - instruction, - Instruction::from_bytes(bytes) - ); - println!("from bytes passed."); - */ - - } - } -} \ No newline at end of file