From 0c475127f6fd4a12a1620fe4795bb41ec41decad Mon Sep 17 00:00:00 2001 From: Trevor Merritt Date: Sun, 29 Jun 2025 10:43:41 -0400 Subject: [PATCH] BUGFIX: Decoder now decodes instructions without parameters --- .bad/.gitignore | 5 +++ .bad/modules.xml | 8 ++++ .bad/mos6502.iml | 13 +++++++ .bad/vcs.xml | 6 +++ .idea/mos6502.iml | 2 + cli/src/bin/decode.rs | 17 +++++++-- core/src/instruction.rs | 70 ++++++++++++++++++----------------- core/src/instruction_table.rs | 4 +- core/src/mos6502cpu.rs | 14 +++++++ 9 files changed, 101 insertions(+), 38 deletions(-) create mode 100644 .bad/.gitignore create mode 100644 .bad/modules.xml create mode 100644 .bad/mos6502.iml create mode 100644 .bad/vcs.xml diff --git a/.bad/.gitignore b/.bad/.gitignore new file mode 100644 index 0000000..b58b603 --- /dev/null +++ b/.bad/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.bad/modules.xml b/.bad/modules.xml new file mode 100644 index 0000000..b4bd04a --- /dev/null +++ b/.bad/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.bad/mos6502.iml b/.bad/mos6502.iml new file mode 100644 index 0000000..02e7b41 --- /dev/null +++ b/.bad/mos6502.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.bad/vcs.xml b/.bad/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.bad/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/mos6502.iml b/.idea/mos6502.iml index fa80a9b..95a2172 100644 --- a/.idea/mos6502.iml +++ b/.idea/mos6502.iml @@ -6,6 +6,8 @@ + + diff --git a/cli/src/bin/decode.rs b/cli/src/bin/decode.rs index fa5a43e..fb6e2b6 100644 --- a/cli/src/bin/decode.rs +++ b/cli/src/bin/decode.rs @@ -1,11 +1,22 @@ use core::instruction::Instruction; use core::address_mode::AddressMode; +use core::operand::Operand; +use core::operation::Operation; fn main() { println!("Taxation is Theft"); - // Instruction::from_bytes(vec![0b11100011]); + let instructions = vec![( + Instruction { + op: Operation::NOP, + mode: AddressMode::Implied, + operand: Operand::None, + }, &[0xea] + )]; - // let instruction = Instruction::ADC(AddressMode::Immediate); - // println!("Instruction = {:?}", instruction.to_string()); + for (op, bytes) in instructions { + assert_eq!(Instruction::decode(bytes), Some(op)); + } + // let instruction = Instruction::decode(&[0xea]); + // println!("NOP Decoded -> {:?}", instruction); } diff --git a/core/src/instruction.rs b/core/src/instruction.rs index fa20365..e931014 100644 --- a/core/src/instruction.rs +++ b/core/src/instruction.rs @@ -15,6 +15,7 @@ pub struct Instruction { impl Instruction { pub fn decode(bytes: &[u8]) -> Option { + println!("DECODING : {bytes:?}"); let opcode = bytes.get(0).copied()?; let info = INSTRUCTION_TABLE[opcode as usize]?; @@ -25,14 +26,18 @@ impl Instruction { let hi = *bytes.get(2)?; Operand::Word(u16::from_le_bytes([lo, hi])) } - _ => return None, + _ => Operand::None, }; - Some(Instruction { + let return_value = Some(Instruction { op: info.operation, mode: info.mode, operand, - }) + }); + + println!("RETURNING: {:?}", return_value); + + return_value } } @@ -41,7 +46,7 @@ impl Instruction { mod test { use crate::address_mode::AddressMode::*; use crate::instruction::Instruction; - use crate::operation::Operation::ADC; + use crate::operation::Operation::{ADC, INY, LSR}; use super::*; #[test] @@ -75,14 +80,14 @@ mod test { (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) }), + (vec![0x10, 0xab], Instruction { op: BPL, mode: Implied, operand: Operand::Byte(0xab) }), + (vec![0x30, 0xab], Instruction { op: BMI, mode: Implied, operand: Operand::Byte(0xab) }), + (vec![0x50, 0xab], Instruction { op: BVC, mode: Implied, operand: Operand::Byte(0xab) }), + (vec![0x70, 0xab], Instruction { op: BVS, mode: Implied, operand: Operand::Byte(0xab) }), + (vec![0x90, 0xab], Instruction { op: BCC, mode: Implied, operand: Operand::Byte(0xab) }), + (vec![0xb0, 0xab], Instruction { op: BCS, mode: Implied, operand: Operand::Byte(0xab) }), + (vec![0xd0, 0xab], Instruction { op: BNE, mode: Implied, operand: Operand::Byte(0xab) }), + (vec![0xf0, 0xab], Instruction { op: BEQ, mode: Implied, operand: Operand::Byte(0xab) }), // BRK (vec![0x00], Instruction { op: BRK, mode: Implied, operand: Operand::None }), // CLC, CLD, CLI, CLV @@ -129,7 +134,7 @@ mod test { (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 }), + (vec![0xc8], Instruction { op: INY, 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) }), @@ -146,21 +151,21 @@ mod test { // 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![0xb6, 0xab], Instruction { op: LDX, mode: ZeroPageY, 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) }), + (vec![0xbe, 0xcd, 0xab], Instruction { op: LDX, mode: AbsoluteY, 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) }), + (vec![0xa0, 0xab], Instruction { op: LDY, mode: Immediate, operand: Operand::Byte(0xab) }), + (vec![0xa4, 0xab], Instruction { op: LDY, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0xb4, 0xab], Instruction { op: LDY, mode: ZeroPageX, operand: Operand::Byte(0xab) }), + (vec![0xac, 0xcd, 0xab], Instruction { op: LDY, mode: Absolute, operand: Operand::Word(0xabcd) }), + (vec![0xbc, 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) }), + (vec![0x4a], Instruction { op: LSR, mode: Accumulator, operand: Operand::None }), + (vec![0x46, 0xab], Instruction { op: LSR, mode: ZeroPage, operand: Operand::Byte(0xab) }), + (vec![0x56, 0xab], Instruction { op: LSR, mode: ZeroPageX, operand: Operand::Byte(0xab) }), + (vec![0x4e, 0xcd, 0xab], Instruction { op: LSR, mode: Absolute, operand: Operand::Word(0xabcd) }), + (vec![0x5e, 0xcd, 0xab], Instruction { op: LSR, mode: AbsoluteX, operand: Operand::Word(0xabcd) }), // NOP (vec![0xea], Instruction { op: NOP, mode: Implied, operand: Operand::None }), // ORA @@ -178,13 +183,13 @@ mod test { (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![0x2a], Instruction { op: ROL, mode: Accumulator, operand: Operand::None }), (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![0x6a], Instruction { op: ROR, mode: Accumulator, operand: Operand::None }), (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) }), @@ -215,7 +220,7 @@ mod test { (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![0x96, 0xab], Instruction { op: STX, mode: ZeroPageY, 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) }), @@ -230,13 +235,12 @@ mod test { (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) + let result1 = Instruction::decode(&bytes); + if let Some(instruction1) = result1 { + assert_eq!(instruction, instruction1) } else { println!("Failed to decode {:?}", bytes); } - } } -} \ No newline at end of file +} diff --git a/core/src/instruction_table.rs b/core/src/instruction_table.rs index 094c7ce..2aac88d 100644 --- a/core/src/instruction_table.rs +++ b/core/src/instruction_table.rs @@ -256,13 +256,13 @@ pub const INSTRUCTION_TABLE: [Option; 256] = { table[ISA_OP_CMP_ABSX as usize] = Some(OpInfo { operation: CMP, mode: AddressMode::AbsoluteX, - length: 2, + length: 3, cycles: 4, }); table[ISA_OP_CMP_ABSY as usize] = Some(OpInfo { operation: CMP, mode: AddressMode::AbsoluteY, - length: 2, + length: 3, cycles: 4, }); table[ISA_OP_CMP_INDX as usize] = Some(OpInfo { diff --git a/core/src/mos6502cpu.rs b/core/src/mos6502cpu.rs index faf2537..aa95535 100644 --- a/core/src/mos6502cpu.rs +++ b/core/src/mos6502cpu.rs @@ -1,3 +1,4 @@ +use crate::instruction::Instruction; use crate::mos6502flags::{Mos6502Flag, Mos6502Flags}; pub const SIZE_1KB: usize = 1024 * 1024; @@ -103,6 +104,15 @@ impl Mos6502Cpu { /// Returns /// AddressBus, DataBus, RW flag pub fn tick(&mut self) -> (u16, u8, bool) { + + let num_microsteps_left = 0; + + if num_microsteps_left == 0 { + // load the microstep buffer with what steps to run + // set the counter to the number of steps left + } + // run 1 microcode step + (0,0,false) } @@ -114,4 +124,8 @@ impl Mos6502Cpu { pub fn dump_data(&self) -> ( u16, u8, u8, u8, u16, u8) { (self.pc, self.a, self.x, self.y, self.address_bus, self.data_bus) } + + fn run_microstep(&self, instruction: Instruction, step: u8) { + + } }