From 00e87de9fe4df6e0cf58a520eddfffa45b8c5b5d Mon Sep 17 00:00:00 2001 From: Franco Colmenarez Date: Tue, 26 Dec 2023 22:27:32 -0500 Subject: [PATCH] common decoding module --- snes-core/src/cpu/instructionstemp/adc.rs | 85 +++++++------ snes-core/src/cpu/instructionstemp/and.rs | 49 ++++---- snes-core/src/cpu/instructionstemp/asl.rs | 45 +++---- .../cpu/instructionstemp/decoder_common.rs | 113 ++++++++++++++++++ snes-core/src/cpu/instructionstemp/mod.rs | 5 +- snes-core/src/utils/addressing.rs | 12 ++ 6 files changed, 209 insertions(+), 100 deletions(-) create mode 100644 snes-core/src/cpu/instructionstemp/decoder_common.rs diff --git a/snes-core/src/cpu/instructionstemp/adc.rs b/snes-core/src/cpu/instructionstemp/adc.rs index 2874464..3f1da85 100644 --- a/snes-core/src/cpu/instructionstemp/adc.rs +++ b/snes-core/src/cpu/instructionstemp/adc.rs @@ -2,106 +2,103 @@ use crate::{cpu::{bus::Bus, registers::Registers}, utils::{alu, addressing::Addr use crate::cpu::cycles; use super::{CPUInstruction, Decode, read_8bit_from_address, read_16bit_from_address}; +use super::decoder_common; -pub const OPCODE: u8 = 0x69; +static INSTR_NAME: &'static str = "ADC"; -fn mnemonic_8bit(registers: &Registers, bus: &Bus) -> String { - let next_byte = bus.read_external(registers.get_pc_address() + 1); - format!("{:02X} {:02X} __ __ | ADC #${:02X}", OPCODE, next_byte, next_byte) +pub struct ADC8BIN { + addressing_mode: AddressingMode, } -fn mnemonic_16bit(registers: &Registers, bus: &Bus) -> String { - let next_byte = bus.read_external(registers.get_pc_address() + 1); - let next_second_byte = bus.read_external(registers.get_pc_address() + 2); - let word = (next_byte as u16) | ((next_byte as u16) << 8); - format!("{:02X} {:02X} {:02X} __ | ADC #${:04X}", OPCODE, next_byte, next_second_byte, word) -} - -pub struct ADC8BIN {} - impl CPUInstruction for ADC8BIN { - fn execute(&self, registers: &mut Registers, bus: &mut Bus, addressing_mode: AddressingMode) { + fn execute(&self, registers: &mut Registers, bus: &mut Bus) { let (result, affected_flags) = alu::adc_bin( registers.a as u8, - read_8bit_from_address(registers, bus, addressing_mode), + read_8bit_from_address(registers, bus, self.addressing_mode), registers.get_carry_flag(), ); registers.set_low_a(result); registers.set_flags(&affected_flags); - let (bytes, cycles) = cycles::increment_cycles_arithmetic(®isters, addressing_mode); + let (bytes, cycles) = cycles::increment_cycles_arithmetic(®isters, self.addressing_mode); registers.increment_pc(bytes); registers.cycles += cycles; } } impl Decode for ADC8BIN { - fn mnemonic(&self, registers: &Registers, bus: &Bus) -> String { - mnemonic_8bit(registers, bus) + fn mnemonic(&self, registers: &Registers, bus: &Bus, opcode: u8) -> String { + decoder_common::mnemonic_arithmetic(false, opcode, INSTR_NAME, self.addressing_mode, registers, bus) } } -pub struct ADC16BIN {} +pub struct ADC16BIN { + addressing_mode: AddressingMode, +} impl CPUInstruction for ADC16BIN { - fn execute(&self, registers: &mut Registers, bus: &mut Bus, addressing_mode: AddressingMode) { + fn execute(&self, registers: &mut Registers, bus: &mut Bus) { let (result, affected_flags) = alu::adc_bin( registers.a, - read_16bit_from_address(registers, bus, addressing_mode), + read_16bit_from_address(registers, bus, self.addressing_mode), registers.get_carry_flag(), ); registers.a = result; registers.set_flags(&affected_flags); - let (bytes, cycles) = cycles::increment_cycles_arithmetic(®isters, addressing_mode); + let (bytes, cycles) = cycles::increment_cycles_arithmetic(®isters, self.addressing_mode); registers.increment_pc(bytes); registers.cycles += cycles; } } impl Decode for ADC16BIN { - fn mnemonic(&self, registers: &Registers, bus: &Bus) -> String { - mnemonic_16bit(registers, bus) + fn mnemonic(&self, registers: &Registers, bus: &Bus, opcode: u8) -> String { + decoder_common::mnemonic_arithmetic(true, opcode, INSTR_NAME, self.addressing_mode, registers, bus) } } -pub struct ADC8BCD {} +pub struct ADC8BCD { + addressing_mode: AddressingMode, +} impl CPUInstruction for ADC8BCD { - fn execute(&self, registers: &mut Registers, bus: &mut Bus, addressing_mode: AddressingMode) { + fn execute(&self, registers: &mut Registers, bus: &mut Bus) { let (result, affected_flags) = alu::adc_bcd( registers.a as u8, - read_8bit_from_address(registers, bus, addressing_mode), + read_8bit_from_address(registers, bus, self.addressing_mode), registers.get_carry_flag(), ); registers.set_low_a(result); registers.set_flags(&affected_flags); - let (bytes, cycles) = cycles::increment_cycles_arithmetic(®isters, addressing_mode); + let (bytes, cycles) = cycles::increment_cycles_arithmetic(®isters, self.addressing_mode); registers.increment_pc(bytes); registers.cycles += cycles; } } impl Decode for ADC8BCD { - fn mnemonic(&self, registers: &Registers, bus: &Bus) -> String { - mnemonic_8bit(registers, bus) + fn mnemonic(&self, registers: &Registers, bus: &Bus, opcode: u8) -> String { + decoder_common::mnemonic_arithmetic(false, opcode, INSTR_NAME, self.addressing_mode, registers, bus) } } -pub struct ADC16BCD {} +pub struct ADC16BCD { + addressing_mode: AddressingMode, +} impl CPUInstruction for ADC16BCD { - fn execute(&self, registers: &mut Registers, bus: &mut Bus, addressing_mode: AddressingMode) { + fn execute(&self, registers: &mut Registers, bus: &mut Bus) { let (result, affected_flags) = alu::adc_bcd( registers.a, - read_16bit_from_address(registers, bus, addressing_mode), + read_16bit_from_address(registers, bus, self.addressing_mode), registers.get_carry_flag(), ); registers.a = result; registers.set_flags(&affected_flags); - let (bytes, cycles) = cycles::increment_cycles_arithmetic(®isters, addressing_mode); + let (bytes, cycles) = cycles::increment_cycles_arithmetic(®isters, self.addressing_mode); registers.increment_pc(bytes); registers.cycles += cycles; } } impl Decode for ADC16BCD { - fn mnemonic(&self, registers: &Registers, bus: &Bus) -> String { - mnemonic_16bit(registers, bus) + fn mnemonic(&self, registers: &Registers, bus: &Bus, opcode: u8) -> String { + decoder_common::mnemonic_arithmetic(true, opcode, INSTR_NAME, self.addressing_mode, registers, bus) } } @@ -120,8 +117,8 @@ mod cpu_instructions_tests { registers.pc = 0x0000; registers.set_memory_select_flag(true); bus.write(0x000001, 0x40); - let instruction = ADC8BIN{}; - instruction.execute(&mut registers, &mut bus, AddressingMode::Immediate); + let instruction = ADC8BIN{addressing_mode: AddressingMode::Immediate}; + instruction.execute(&mut registers, &mut bus); assert_eq!(registers.a, 0x40); assert_eq!(registers.pc, 0x02); assert_eq!(registers.cycles, 2); @@ -139,8 +136,8 @@ mod cpu_instructions_tests { registers.set_memory_select_flag(false); bus.write(0x000001, 0x00); bus.write(0x000002, 0x40); - let instruction = ADC16BIN{}; - instruction.execute(&mut registers, &mut bus, AddressingMode::Immediate); + let instruction = ADC16BIN{addressing_mode: AddressingMode::Immediate}; + instruction.execute(&mut registers, &mut bus); assert_eq!(registers.a, 0x4000); assert_eq!(registers.pc, 0x03); assert_eq!(registers.cycles, 3); @@ -157,8 +154,8 @@ mod cpu_instructions_tests { registers.pc = 0x0000; registers.set_memory_select_flag(true); bus.write(0x000001, 0x40); - let instruction = ADC8BCD{}; - instruction.execute(&mut registers, &mut bus, AddressingMode::Immediate); + let instruction = ADC8BCD{addressing_mode: AddressingMode::Immediate}; + instruction.execute(&mut registers, &mut bus); assert_eq!(registers.a, 0x40); assert_eq!(registers.pc, 0x02); assert_eq!(registers.cycles, 2); @@ -176,8 +173,8 @@ mod cpu_instructions_tests { registers.set_memory_select_flag(false); bus.write(0x000001, 0x00); bus.write(0x000002, 0x40); - let instruction = ADC16BCD{}; - instruction.execute(&mut registers, &mut bus, AddressingMode::Immediate); + let instruction = ADC16BCD{addressing_mode: AddressingMode::Immediate}; + instruction.execute(&mut registers, &mut bus); assert_eq!(registers.a, 0x4000); assert_eq!(registers.pc, 0x03); assert_eq!(registers.cycles, 3); diff --git a/snes-core/src/cpu/instructionstemp/and.rs b/snes-core/src/cpu/instructionstemp/and.rs index 3296790..9d6a6e4 100644 --- a/snes-core/src/cpu/instructionstemp/and.rs +++ b/snes-core/src/cpu/instructionstemp/and.rs @@ -2,60 +2,53 @@ use crate::{cpu::{bus::Bus, registers::Registers}, utils::{alu, addressing::Addr use crate::cpu::cycles; use super::{CPUInstruction, Decode, read_8bit_from_address, read_16bit_from_address}; +use super::decoder_common; -pub const OPCODE: u8 = 0x29; +static INSTR_NAME: &'static str = "AND"; -fn mnemonic_8bit(registers: &Registers, bus: &Bus) -> String { - let next_byte = bus.read_external(registers.get_pc_address() + 1); - format!("{:02X} {:02X} __ __ | AND #${:02X}", OPCODE, next_byte, next_byte) +pub struct AND8 { + addressing_mode: AddressingMode, } -fn mnemonic_16bit(registers: &Registers, bus: &Bus) -> String { - let next_byte = bus.read_external(registers.get_pc_address() + 1); - let next_second_byte = bus.read_external(registers.get_pc_address() + 2); - let word = (next_byte as u16) | ((next_byte as u16) << 8); - format!("{:02X} {:02X} {:02X} __ | AND #${:04X}", OPCODE, next_byte, next_second_byte, word) -} - -pub struct AND8 {} - impl CPUInstruction for AND8 { - fn execute(&self, registers: &mut Registers, bus: &mut Bus, addressing_mode: AddressingMode) { + fn execute(&self, registers: &mut Registers, bus: &mut Bus) { let (result, affected_flags) = alu::and( registers.a as u8, - read_8bit_from_address(registers, bus, addressing_mode), + read_8bit_from_address(registers, bus, self.addressing_mode), ); registers.set_low_a(result); registers.set_flags(&affected_flags); - let (bytes, cycles) = cycles::increment_cycles_bitwise(®isters, addressing_mode); + let (bytes, cycles) = cycles::increment_cycles_bitwise(®isters, self.addressing_mode); registers.increment_pc(bytes); registers.cycles += cycles; } } impl Decode for AND8 { - fn mnemonic(&self, registers: &Registers, bus: &Bus) -> String { - mnemonic_8bit(registers, bus) + fn mnemonic(&self, registers: &Registers, bus: &Bus, opcode: u8) -> String { + decoder_common::mnemonic_arithmetic(false, opcode, INSTR_NAME, self.addressing_mode, registers, bus) } } -pub struct AND16 {} +pub struct AND16 { + addressing_mode: AddressingMode, +} impl CPUInstruction for AND16 { - fn execute(&self, registers: &mut Registers, bus: &mut Bus, addressing_mode: AddressingMode) { + fn execute(&self, registers: &mut Registers, bus: &mut Bus) { let (result, affected_flags) = alu::and( registers.a, - read_16bit_from_address(registers, bus, addressing_mode), + read_16bit_from_address(registers, bus, self.addressing_mode), ); registers.a = result; registers.set_flags(&affected_flags); - let (bytes, cycles) = cycles::increment_cycles_bitwise(®isters, addressing_mode); + let (bytes, cycles) = cycles::increment_cycles_bitwise(®isters, self.addressing_mode); registers.increment_pc(bytes); registers.cycles += cycles; } } impl Decode for AND16 { - fn mnemonic(&self, registers: &Registers, bus: &Bus) -> String { - mnemonic_16bit(registers, bus) + fn mnemonic(&self, registers: &Registers, bus: &Bus, opcode: u8) -> String { + decoder_common::mnemonic_arithmetic(true, opcode, INSTR_NAME, self.addressing_mode, registers, bus) } } @@ -74,8 +67,8 @@ mod cpu_instructions_tests { registers.pc = 0x0000; registers.set_memory_select_flag(true); bus.write(0x000001, 0x00); - let instruction = AND8{}; - instruction.execute(&mut registers, &mut bus, AddressingMode::Immediate); + let instruction = AND8{addressing_mode: AddressingMode::Immediate}; + instruction.execute(&mut registers, &mut bus); assert_eq!(registers.a, 0x0100); assert_eq!(registers.pc, 0x02); assert_eq!(registers.cycles, 2); @@ -94,8 +87,8 @@ mod cpu_instructions_tests { registers.set_memory_select_flag(false); bus.write(0x000001, 0x01); bus.write(0x000002, 0x01); - let instruction = AND16{}; - instruction.execute(&mut registers, &mut bus, AddressingMode::Immediate); + let instruction = AND16{addressing_mode: AddressingMode::Immediate}; + instruction.execute(&mut registers, &mut bus); assert_eq!(registers.a, 0x0101); assert_eq!(registers.pc, 0x03); assert_eq!(registers.cycles, 3); diff --git a/snes-core/src/cpu/instructionstemp/asl.rs b/snes-core/src/cpu/instructionstemp/asl.rs index 642d5d6..a593432 100644 --- a/snes-core/src/cpu/instructionstemp/asl.rs +++ b/snes-core/src/cpu/instructionstemp/asl.rs @@ -2,58 +2,51 @@ use crate::{cpu::{bus::Bus, registers::Registers}, utils::{alu, addressing::Addr use crate::cpu::cycles; use super::{CPUInstruction, Decode}; +use super::decoder_common; -pub const OPCODE: u8 = 0x0A; +static INSTR_NAME: &'static str = "ASL"; -fn mnemonic_8bit(registers: &Registers, bus: &Bus) -> String { - let next_byte = bus.read_external(registers.get_pc_address() + 1); - format!("{:02X} {:02X} __ __ | ASL #${:02X}", OPCODE, next_byte, next_byte) +pub struct ASL8 { + addressing_mode: AddressingMode, } -fn mnemonic_16bit(registers: &Registers, bus: &Bus) -> String { - let next_byte = bus.read_external(registers.get_pc_address() + 1); - let next_second_byte = bus.read_external(registers.get_pc_address() + 2); - let word = (next_byte as u16) | ((next_byte as u16) << 8); - format!("{:02X} {:02X} {:02X} __ | AND #${:04X}", OPCODE, next_byte, next_second_byte, word) -} - -pub struct ASL8 {} - impl CPUInstruction for ASL8 { - fn execute(&self, registers: &mut Registers, _bus: &mut Bus, addressing_mode: AddressingMode) { + fn execute(&self, registers: &mut Registers, _bus: &mut Bus) { let (result, affected_flags) = alu::asl( registers.a as u8, ); registers.set_low_a(result); registers.set_flags(&affected_flags); - let (bytes, cycles) = cycles::increment_cycles_bitwise(®isters, addressing_mode); + let (bytes, cycles) = cycles::increment_cycles_bitwise(®isters, self.addressing_mode); registers.increment_pc(bytes); registers.cycles += cycles; } } impl Decode for ASL8 { - fn mnemonic(&self, registers: &Registers, bus: &Bus) -> String { - mnemonic_8bit(registers, bus) + fn mnemonic(&self, registers: &Registers, bus: &Bus, opcode: u8) -> String { + decoder_common::mnemonic_arithmetic(false, opcode, INSTR_NAME, self.addressing_mode, registers, bus) } } -pub struct ASL16 {} +pub struct ASL16 { + addressing_mode: AddressingMode, +} impl CPUInstruction for ASL16 { - fn execute(&self, registers: &mut Registers, _bus: &mut Bus, addressing_mode: AddressingMode) { + fn execute(&self, registers: &mut Registers, _bus: &mut Bus) { let (result, affected_flags) = alu::asl( registers.a, ); registers.a = result; registers.set_flags(&affected_flags); - let (bytes, cycles) = cycles::increment_cycles_bitwise(®isters, addressing_mode); + let (bytes, cycles) = cycles::increment_cycles_bitwise(®isters, self.addressing_mode); registers.increment_pc(bytes); registers.cycles += cycles; } } impl Decode for ASL16 { - fn mnemonic(&self, registers: &Registers, bus: &Bus) -> String { - mnemonic_16bit(registers, bus) + fn mnemonic(&self, registers: &Registers, bus: &Bus, opcode: u8) -> String { + decoder_common::mnemonic_arithmetic(true, opcode, INSTR_NAME, self.addressing_mode, registers, bus) } } @@ -71,8 +64,8 @@ mod cpu_instructions_tests { registers.pbr = 0x00; registers.pc = 0x0000; registers.set_memory_select_flag(true); - let instruction = ASL8{}; - instruction.execute(&mut registers, &mut bus, AddressingMode::Immediate); + let instruction = ASL8{addressing_mode: AddressingMode::Immediate}; + instruction.execute(&mut registers, &mut bus); assert_eq!(registers.a, 0b10100000); assert_eq!(registers.pc, 0x02); assert_eq!(registers.cycles, 2); @@ -90,8 +83,8 @@ mod cpu_instructions_tests { registers.pbr = 0x00; registers.pc = 0x0000; registers.set_memory_select_flag(false); - let instruction = ASL16{}; - instruction.execute(&mut registers, &mut bus, AddressingMode::Immediate); + let instruction = ASL16{addressing_mode: AddressingMode::Immediate}; + instruction.execute(&mut registers, &mut bus); assert_eq!(registers.a, 0b10100000_00000000); assert_eq!(registers.pc, 0x03); assert_eq!(registers.cycles, 3); diff --git a/snes-core/src/cpu/instructionstemp/decoder_common.rs b/snes-core/src/cpu/instructionstemp/decoder_common.rs new file mode 100644 index 0000000..48ab4b0 --- /dev/null +++ b/snes-core/src/cpu/instructionstemp/decoder_common.rs @@ -0,0 +1,113 @@ +use crate::cpu::registers::Registers; +use crate::cpu::bus::Bus; +use crate::utils::addressing::{IndexRegister, AddressingMode}; + +pub fn mnemonic_arithmetic(is_16bit: bool, opcode: u8, instr_name: &str, addressing_mode: AddressingMode, registers: &Registers, bus: &Bus) -> String { + type A = AddressingMode; + match addressing_mode { + A::Accumulator => mnemonic_accumulator(opcode, instr_name), + A::Immediate => match is_16bit { + true => mnemonic_16bit_immediate(opcode, instr_name, registers, bus), + false => mnemonic_8bit_immediate(opcode, instr_name, registers, bus), + }, + A::Absolute => mnemonic_absolute(opcode, instr_name, registers, bus), + A::AbsoluteLong => mnemonic_absolute_long(opcode, instr_name, registers, bus), + A::DirectPage => mnemonic_direct_page(opcode, instr_name, registers, bus), + A::DirectPageIndirect => mnemonic_direct_page_indirect(opcode, instr_name, registers, bus), + A::DirectPageIndirectLong => mnemonic_direct_page_indirect_long(opcode, instr_name, registers, bus), + A::AbsoluteIndexed(idx) => mnemonic_absolute_indexed(opcode, instr_name, idx, registers, bus), + A::AbsoluteLongIndexed(idx) => mnemonic_absolute_long_indexed(opcode, instr_name, idx, registers, bus), + A::DirectPageIndexed(idx) => mnemonic_direct_page_indexed(opcode, instr_name, idx, registers, bus), + A::DirectPageIndexedIndirect(idx) => mnemonic_direct_page_indexed_indirect(opcode, instr_name, idx, registers, bus), + A::DirectPageIndirectLongIndexed(idx) => mnemonic_direct_page_indirect_long_indexed(opcode, instr_name, idx, registers, bus), + A::StackRelative => mnemonic_stack_relative(opcode, instr_name, registers, bus), + A::StackRelativeIndirectIndexed(idx)=> mnemonic_stack_relative_indirect_indexed(opcode, instr_name, idx, registers, bus), + _ => unreachable!(), + } +} + +pub fn mnemonic_accumulator(opcode: u8, instr_name: &str) -> String { + format!("{:02X} __ __ __ | {} A", opcode, instr_name) +} + +pub fn mnemonic_8bit_immediate(opcode: u8, instr_name: &str, registers: &Registers, bus: &Bus) -> String { + let next_byte = bus.read_external(registers.get_pc_address() + 1); + format!("{:02X} {:02X} __ __ | {} #${:04X}", opcode, next_byte, instr_name, next_byte) +} + +pub fn mnemonic_16bit_immediate(opcode: u8, instr_name: &str, registers: &Registers, bus: &Bus) -> String { + let next_byte = bus.read_external(registers.get_pc_address() + 1); + let next_second_byte = bus.read_external(registers.get_pc_address() + 2); + let word = (next_byte as u16) | ((next_byte as u16) << 8); + format!("{:02X} {:02X} {:02X} __ | {} #${:04X}", opcode, next_byte, next_second_byte, instr_name, word) +} + +pub fn mnemonic_absolute(opcode: u8, instr_name: &str, registers: &Registers, bus: &Bus) -> String { + let next_byte = bus.read_external(registers.get_pc_address() + 1); + let next_second_byte = bus.read_external(registers.get_pc_address() + 2); + let word = (next_byte as u16) | ((next_byte as u16) << 8); + format!("{:02X} {:02X} {:02X} __ | {} ${:04X}", opcode, next_byte, next_second_byte, instr_name, word) +} + +pub fn mnemonic_absolute_long(opcode: u8, instr_name: &str, registers: &Registers, bus: &Bus) -> String { + let next_byte = bus.read_external(registers.get_pc_address() + 1); + let next_second_byte = bus.read_external(registers.get_pc_address() + 2); + let next_third_byte = bus.read_external(registers.get_pc_address() + 3); + let word_long = (next_byte as u32) | ((next_second_byte as u32) << 8) | ((next_third_byte as u32) << 16); + format!("{:02X} {:02X} {:02X} {:02X} | {} ${:06X}", opcode, next_byte, next_second_byte, next_third_byte, instr_name, word_long) +} + +pub fn mnemonic_direct_page(opcode: u8, instr_name: &str, registers: &Registers, bus: &Bus) -> String { + let next_byte = bus.read_external(registers.get_pc_address() + 1); + format!("{:02X} {:02X} __ __ | {} ${:02X} | dp", opcode, next_byte, instr_name, next_byte) +} + +pub fn mnemonic_direct_page_indirect(opcode: u8, instr_name: &str, registers: &Registers, bus: &Bus) -> String { + let next_byte = bus.read_external(registers.get_pc_address() + 1); + format!("{:02X} {:02X} __ __ | {} (${:02X})", opcode, next_byte, instr_name, next_byte) +} + +pub fn mnemonic_direct_page_indirect_long(opcode: u8, instr_name: &str, registers: &Registers, bus: &Bus) -> String { + let next_byte = bus.read_external(registers.get_pc_address() + 1); + format!("{:02X} {:02X} __ __ | {} [${:02X}]", opcode, next_byte, instr_name, next_byte) +} + +pub fn mnemonic_absolute_indexed(opcode: u8, instr_name: &str, index: IndexRegister, registers: &Registers, bus: &Bus) -> String { + let next_byte = bus.read_external(registers.get_pc_address() + 1); + let next_second_byte = bus.read_external(registers.get_pc_address() + 2); + let word = (next_byte as u16) | ((next_byte as u16) << 8); + format!("{:02X} {:02X} {:02X} __ | {} ${:04X}, {}", opcode, next_byte, next_second_byte, instr_name, word, index) +} + +pub fn mnemonic_absolute_long_indexed(opcode: u8, instr_name: &str, index: IndexRegister, registers: &Registers, bus: &Bus) -> String { + let next_byte = bus.read_external(registers.get_pc_address() + 1); + let next_second_byte = bus.read_external(registers.get_pc_address() + 2); + let next_third_byte = bus.read_external(registers.get_pc_address() + 3); + let word_long = (next_byte as u32) | ((next_second_byte as u32) << 8) | ((next_third_byte as u32) << 16); + format!("{:02X} {:02X} {:02X} {:02X} | {} ${:06X}, {}", opcode, next_byte, next_second_byte, next_third_byte, instr_name, word_long, index) +} + +pub fn mnemonic_direct_page_indexed(opcode: u8, instr_name: &str, index: IndexRegister, registers: &Registers, bus: &Bus) -> String { + let next_byte = bus.read_external(registers.get_pc_address() + 1); + format!("{:02X} {:02X} __ __ | {} ${:02X}, {} | dp", opcode, next_byte, instr_name, next_byte, index) +} + +pub fn mnemonic_direct_page_indexed_indirect(opcode: u8, instr_name: &str, index: IndexRegister, registers: &Registers, bus: &Bus) -> String { + let next_byte = bus.read_external(registers.get_pc_address() + 1); + format!("{:02X} {:02X} __ __ | {} (${:02X}, {}) | dp", opcode, next_byte, instr_name, next_byte, index) +} + +pub fn mnemonic_direct_page_indirect_long_indexed(opcode: u8, instr_name: &str, index: IndexRegister, registers: &Registers, bus: &Bus) -> String { + let next_byte = bus.read_external(registers.get_pc_address() + 1); + format!("{:02X} {:02X} __ __ | {} [${:02X}], {} | dp", opcode, next_byte, instr_name, next_byte, index) +} + +pub fn mnemonic_stack_relative(opcode: u8, instr_name: &str, registers: &Registers, bus: &Bus) -> String { + let next_byte = bus.read_external(registers.get_pc_address() + 1); + format!("{:02X} {:02X} __ __ | {} ${:02X}, S", opcode, next_byte, instr_name, next_byte) +} + +pub fn mnemonic_stack_relative_indirect_indexed(opcode: u8, instr_name: &str, index: IndexRegister, registers: &Registers, bus: &Bus) -> String { + let next_byte = bus.read_external(registers.get_pc_address() + 1); + format!("{:02X} {:02X} __ __ | {} (${:02X}, S), {}", opcode, next_byte, instr_name, next_byte, index) +} diff --git a/snes-core/src/cpu/instructionstemp/mod.rs b/snes-core/src/cpu/instructionstemp/mod.rs index 2364c1c..6742268 100644 --- a/snes-core/src/cpu/instructionstemp/mod.rs +++ b/snes-core/src/cpu/instructionstemp/mod.rs @@ -5,13 +5,14 @@ use crate::utils::addressing::AddressingMode; pub mod adc; pub mod and; pub mod asl; +pub mod decoder_common; pub trait CPUInstruction { - fn execute(&self, registers: &mut Registers, bus: &mut Bus, addressing_mode: AddressingMode); + fn execute(&self, registers: &mut Registers, bus: &mut Bus); } pub trait Decode { - fn mnemonic(&self, registers: &Registers, bus: &Bus) -> String; + fn mnemonic(&self, registers: &Registers, bus: &Bus, opcode: u8) -> String; } pub fn read_8bit_from_address(registers: &Registers, bus: &mut Bus, addressing_mode: AddressingMode) -> u8 { diff --git a/snes-core/src/utils/addressing.rs b/snes-core/src/utils/addressing.rs index 440ec57..6f45982 100644 --- a/snes-core/src/utils/addressing.rs +++ b/snes-core/src/utils/addressing.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + use crate::cpu::bus::Bus; /// OPCODE #const @@ -114,6 +116,16 @@ pub enum IndexRegister { X, Y, } +impl Display for IndexRegister { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let name = match self { + IndexRegister::X => "X", + IndexRegister::Y => "Y", + }; + write!(f, "{}", name) + } +} + #[derive(Copy, Clone)] pub enum AddressingMode { Accumulator,