From e68e9f22815a245eeaa0bd42fbd6b300ebaee76e Mon Sep 17 00:00:00 2001 From: Franco Colmenarez Date: Mon, 11 Mar 2024 22:01:47 -0500 Subject: [PATCH] Fix break instructions and mark broken instructions --- snes-core/src/cpu/instructions/brk.rs | 15 +++++++++------ snes-core/src/cpu/instructions/brl.rs | 16 ++++++++-------- snes-core/src/cpu/instructions/cop.rs | 11 +++++++---- snes-core/src/cpu/instructions/mapper.rs | 6 +++--- 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/snes-core/src/cpu/instructions/brk.rs b/snes-core/src/cpu/instructions/brk.rs index 1b8b866..a3ab59a 100644 --- a/snes-core/src/cpu/instructions/brk.rs +++ b/snes-core/src/cpu/instructions/brk.rs @@ -12,15 +12,18 @@ pub struct BRK {} impl CPUInstruction for BRK { fn execute(&self, registers: &mut Registers, bus: &mut Bus) { push_common::do_push(registers, bus, &[registers.pbr]); - push_common::do_push(registers, bus, &[(registers.pc >> 8) as u8, registers.pc as u8]); - push_common::do_push(registers, bus, &[registers.p]); - registers.set_decimal_mode_flag(false); - registers.set_irq_disable_flag(true); let (bytes, cycles) = cycles::increment_cycles_brk(registers.emulation_mode); registers.increment_pc(bytes); registers.cycles += cycles; + push_common::do_push(registers, bus, &[(registers.pc >> 8) as u8, registers.pc as u8]); + push_common::do_push(registers, bus, &[registers.p]); + registers.set_irq_disable_flag(true); + registers.pbr = 0x00; + let vector = (bus.read(0x00FFE6) as u16) | ((bus.read(0x00FFE7) as u16) << 8); + registers.pc = vector; + registers.set_decimal_mode_flag(false); } - fn mnemonic(&self, _registers: &Registers, _bus: &Bus, opcode: u8) -> String { - decoder_common::mnemonic_single_byte_instr(opcode, INSTR_NAME) + fn mnemonic(&self, registers: &Registers, bus: &Bus, opcode: u8) -> String { + decoder_common::mnemonic_8bit_immediate(opcode, INSTR_NAME, registers, bus) } } diff --git a/snes-core/src/cpu/instructions/brl.rs b/snes-core/src/cpu/instructions/brl.rs index 4847f84..c75eb71 100644 --- a/snes-core/src/cpu/instructions/brl.rs +++ b/snes-core/src/cpu/instructions/brl.rs @@ -10,14 +10,14 @@ pub struct BRL {} impl CPUInstruction for BRL { fn execute(&self, registers: &mut Registers, bus: &mut Bus) { - let label = bus.read(registers.get_pc_address()) as u16 | - ((bus.read(registers.get_pc_address() + 1) as u16) << 8); + let label = bus.read(registers.get_pc_address() + 1) as u16 | + ((bus.read(registers.get_pc_address() + 2) as u16) << 8); let is_negative = (label >> 15) != 0; if is_negative { let label = !label + 1; - registers.decrement_pc(label); + registers.pc = registers.pc.wrapping_sub(label); } else { - registers.increment_pc(label); + registers.pc = registers.pc.wrapping_add(label); } let (bytes, cycles) = cycles::increment_cycles_branch_long(); registers.increment_pc(bytes); registers.cycles += cycles; @@ -42,18 +42,18 @@ mod cpu_instructions_tests { let mut bus = Bus::new(); registers.pc = 0x0001; registers.cycles = 0; - bus.write(0x01, 0b00000000); - bus.write(0x02, 0b00001111); + bus.write(0x02, 0b00000000); + bus.write(0x03, 0b00001111); instruction.execute(&mut registers, &mut bus); assert_eq!(registers.pc, 0x04 + 0b00001111_00000000); assert_eq!(registers.cycles, 4); // test with negative nearlabel and boundary cross - registers.pc = 0x00FD; + registers.pc = 0x00FC; registers.cycles = 0; bus.write(0xFD, 0xFF); // write -1 bus.write(0xFE, 0xFF); // write -1 instruction.execute(&mut registers, &mut bus); - assert_eq!(registers.pc, 0xFF); + assert_eq!(registers.pc, 0xFE); assert_eq!(registers.cycles, 4); } } diff --git a/snes-core/src/cpu/instructions/cop.rs b/snes-core/src/cpu/instructions/cop.rs index 10d59a1..3c5efe4 100644 --- a/snes-core/src/cpu/instructions/cop.rs +++ b/snes-core/src/cpu/instructions/cop.rs @@ -12,12 +12,15 @@ pub struct COP {} impl CPUInstruction for COP { fn execute(&self, registers: &mut Registers, bus: &mut Bus) { push_common::do_push(registers, bus, &[registers.pbr]); - push_common::do_push(registers, bus, &[(registers.pc >> 8) as u8, registers.pc as u8]); - push_common::do_push(registers, bus, &[registers.p]); - registers.set_decimal_mode_flag(false); - registers.set_irq_disable_flag(true); let (bytes, cycles) = cycles::increment_cycles_brk(registers.emulation_mode); registers.increment_pc(bytes); registers.cycles += cycles; + push_common::do_push(registers, bus, &[(registers.pc >> 8) as u8, registers.pc as u8]); + push_common::do_push(registers, bus, &[registers.p]); + registers.set_irq_disable_flag(true); + registers.pbr = 0x00; + let vector = (bus.read(0x00FFE4) as u16) | ((bus.read(0x00FFE5) as u16) << 8); + registers.pc = vector; + registers.set_decimal_mode_flag(false); } fn mnemonic(&self, _registers: &Registers, _bus: &Bus, opcode: u8) -> String { diff --git a/snes-core/src/cpu/instructions/mapper.rs b/snes-core/src/cpu/instructions/mapper.rs index 0c3a895..b7c2ec8 100644 --- a/snes-core/src/cpu/instructions/mapper.rs +++ b/snes-core/src/cpu/instructions/mapper.rs @@ -150,7 +150,7 @@ pub fn map_opcode_to_instruction(opcode: u8) -> Box { 0xDC => Box::new(JMP{addressing_mode: A::AbsoluteIndirectLong}), // JSR 0x20 => Box::new(JSR{addressing_mode: A::Absolute}), - 0xFC => Box::new(JSR{addressing_mode: A::AbsoluteIndexedIndirect(I::X)}), + 0xFC => Box::new(JSR{addressing_mode: A::AbsoluteIndexedIndirect(I::X)}), // TODO: Broken 0x22 => Box::new(JSR{addressing_mode: A::AbsoluteLong}), // same as JSL // LDA 0xA9 => Box::new(LDA{addressing_mode: A::Immediate}), @@ -187,9 +187,9 @@ pub fn map_opcode_to_instruction(opcode: u8) -> Box { 0x5E => Box::new(LSR{addressing_mode: A::AbsoluteIndexed(I::X)}), 0x56 => Box::new(LSR{addressing_mode: A::DirectPageIndexed(I::X)}), // MVN - 0x54 => Box::new(MVN{}), + 0x54 => Box::new(MVN{}), // TODO: Broken // MVP - 0x44 => Box::new(MVP{}), + 0x44 => Box::new(MVP{}), // TODO: Broken // NOP 0xEA => Box::new(NOP{}), // ORA