use crate::machine::{Cpu, MemoryReadOnly};
use crate::{Address, UnknownOpcode};
use std::fmt;
#[derive(Debug, Clone, Copy)]
pub enum InstructionType {
Adc,
Ahx,
Alr,
Arr,
Anc,
And,
Asl,
Axs,
Bcc,
Bcs,
Beq,
Bmi,
Bne,
Bpl,
Brk,
Bvc,
Bvs,
Bit,
Clc,
Cld,
Cli,
Clv,
Cmp,
Cpx,
Cpy,
Dcp,
Dec,
Dex,
Dey,
Eor,
Ign,
Inc,
Inx,
Iny,
Isc,
Jmp,
Jsr,
Lax,
Lda,
Ldx,
Ldy,
Lsr,
Nop,
Ora,
Pha,
Php,
Pla,
Plp,
Rla,
Rol,
Ror,
Rra,
Rti,
Rts,
Sax,
Sbc,
Sec,
Sed,
Sei,
Skb,
Slo,
Sre,
Sta,
Stx,
Sty,
Sxa,
Sya,
Tax,
Tay,
Tsx,
Txa,
Txs,
Tya,
}
#[derive(Debug, Clone, Copy)]
pub enum AddressingMode {
Absolute,
AbsoluteXIndexed,
AbsoluteYIndexed,
Accumulator,
Implied,
Immediate,
Indirect,
IndirectYIndexed,
Relative,
XIndexedIndirect,
ZeroPage,
ZeroPageXIndexed,
ZeroPageYIndexed,
}
impl AddressingMode {
fn operand_bytes(self) -> usize {
use AddressingMode::*;
match self {
Absolute => 2,
AbsoluteXIndexed => 2,
AbsoluteYIndexed => 2,
Implied => 0,
Accumulator => 0,
Immediate => 1,
Indirect => 2,
IndirectYIndexed => 1,
Relative => 1,
XIndexedIndirect => 1,
ZeroPage => 1,
ZeroPageXIndexed => 1,
ZeroPageYIndexed => 1,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct Instruction {
instruction_type: InstructionType,
addressing_mode: AddressingMode,
}
impl Instruction {
fn new(instruction_type: InstructionType, addressing_mode: AddressingMode) -> Self {
Self {
instruction_type,
addressing_mode,
}
}
pub fn size(&self) -> usize {
self.addressing_mode.operand_bytes() + 1
}
pub fn from_opcode(opcode: u8) -> Result<Self, UnknownOpcode> {
use crate::opcode;
use AddressingMode::*;
use InstructionType::*;
let (instruction_type, addressing_mode) = match opcode {
opcode::adc::ABSOLUTE => (Adc, Absolute),
opcode::adc::ABSOLUTE_X_INDEXED => (Adc, AbsoluteXIndexed),
opcode::adc::ABSOLUTE_Y_INDEXED => (Adc, AbsoluteYIndexed),
opcode::adc::IMMEDIATE => (Adc, Immediate),
opcode::adc::INDIRECT_Y_INDEXED => (Adc, IndirectYIndexed),
opcode::adc::X_INDEXED_INDIRECT => (Adc, XIndexedIndirect),
opcode::adc::ZERO_PAGE => (Adc, ZeroPage),
opcode::adc::ZERO_PAGE_X_INDEXED => (Adc, ZeroPageXIndexed),
opcode::ahx::unofficial0::ABSOLUTE_Y_INDEXED => (Ahx, AbsoluteYIndexed),
opcode::ahx::unofficial0::INDIRECT_Y_INDEXED => (Ahx, IndirectYIndexed),
opcode::alr::unofficial0::IMMEDIATE => (Alr, Immediate),
opcode::arr::unofficial0::IMMEDIATE => (Arr, Immediate),
opcode::anc::unofficial0::IMMEDIATE => (Anc, Immediate),
opcode::anc::unofficial1::IMMEDIATE => (Anc, Immediate),
opcode::and::ABSOLUTE => (And, Absolute),
opcode::and::ABSOLUTE_X_INDEXED => (And, AbsoluteXIndexed),
opcode::and::ABSOLUTE_Y_INDEXED => (And, AbsoluteYIndexed),
opcode::and::IMMEDIATE => (And, Immediate),
opcode::and::INDIRECT_Y_INDEXED => (And, IndirectYIndexed),
opcode::and::X_INDEXED_INDIRECT => (And, XIndexedIndirect),
opcode::and::ZERO_PAGE => (And, ZeroPage),
opcode::and::ZERO_PAGE_X_INDEXED => (And, ZeroPageXIndexed),
opcode::asl::ABSOLUTE => (Asl, Absolute),
opcode::asl::ABSOLUTE_X_INDEXED => (Asl, AbsoluteXIndexed),
opcode::asl::ACCUMULATOR => (Asl, Accumulator),
opcode::asl::ZERO_PAGE => (Asl, ZeroPage),
opcode::asl::ZERO_PAGE_X_INDEXED => (Asl, ZeroPageXIndexed),
opcode::axs::unofficial0::IMMEDIATE => (Axs, Immediate),
opcode::bcc::RELATIVE => (Bcc, Relative),
opcode::bcs::RELATIVE => (Bcs, Relative),
opcode::beq::RELATIVE => (Beq, Relative),
opcode::bmi::RELATIVE => (Bmi, Relative),
opcode::bne::RELATIVE => (Bne, Relative),
opcode::bpl::RELATIVE => (Bpl, Relative),
opcode::brk::IMPLIED => (Brk, Implied),
opcode::bvc::RELATIVE => (Bvc, Relative),
opcode::bvs::RELATIVE => (Bvs, Relative),
opcode::bit::ABSOLUTE => (Bit, Absolute),
opcode::bit::ZERO_PAGE => (Bit, ZeroPage),
opcode::clc::IMPLIED => (Clc, Implied),
opcode::cld::IMPLIED => (Cld, Implied),
opcode::cli::IMPLIED => (Cli, Implied),
opcode::clv::IMPLIED => (Clv, Implied),
opcode::cmp::ABSOLUTE => (Cmp, Absolute),
opcode::cmp::ABSOLUTE_X_INDEXED => (Cmp, AbsoluteXIndexed),
opcode::cmp::ABSOLUTE_Y_INDEXED => (Cmp, AbsoluteYIndexed),
opcode::cmp::IMMEDIATE => (Cmp, Immediate),
opcode::cmp::INDIRECT_Y_INDEXED => (Cmp, IndirectYIndexed),
opcode::cmp::X_INDEXED_INDIRECT => (Cmp, XIndexedIndirect),
opcode::cmp::ZERO_PAGE => (Cmp, ZeroPage),
opcode::cmp::ZERO_PAGE_X_INDEXED => (Cmp, ZeroPageXIndexed),
opcode::cpx::ABSOLUTE => (Cpx, Absolute),
opcode::cpx::IMMEDIATE => (Cpx, Immediate),
opcode::cpx::ZERO_PAGE => (Cpx, ZeroPage),
opcode::cpy::ABSOLUTE => (Cpy, Absolute),
opcode::cpy::IMMEDIATE => (Cpy, Immediate),
opcode::cpy::ZERO_PAGE => (Cpy, ZeroPage),
opcode::dcp::unofficial0::X_INDEXED_INDIRECT => (Dcp, XIndexedIndirect),
opcode::dcp::unofficial0::ZERO_PAGE => (Dcp, ZeroPage),
opcode::dcp::unofficial0::ABSOLUTE => (Dcp, Absolute),
opcode::dcp::unofficial0::INDIRECT_Y_INDEXED => (Dcp, IndirectYIndexed),
opcode::dcp::unofficial0::ZERO_PAGE_X_INDEXED => (Dcp, ZeroPageXIndexed),
opcode::dcp::unofficial0::ABSOLUTE_X_INDEXED => (Dcp, AbsoluteXIndexed),
opcode::dcp::unofficial0::ABSOLUTE_Y_INDEXED => (Dcp, AbsoluteYIndexed),
opcode::dec::ABSOLUTE => (Dec, Absolute),
opcode::dec::ABSOLUTE_X_INDEXED => (Dec, AbsoluteXIndexed),
opcode::dec::ZERO_PAGE => (Dec, ZeroPage),
opcode::dec::ZERO_PAGE_X_INDEXED => (Dec, ZeroPageXIndexed),
opcode::dex::IMPLIED => (Dex, Implied),
opcode::dey::IMPLIED => (Dey, Implied),
opcode::eor::ABSOLUTE => (Eor, Absolute),
opcode::eor::ABSOLUTE_X_INDEXED => (Eor, AbsoluteXIndexed),
opcode::eor::ABSOLUTE_Y_INDEXED => (Eor, AbsoluteYIndexed),
opcode::eor::IMMEDIATE => (Eor, Immediate),
opcode::eor::INDIRECT_Y_INDEXED => (Eor, IndirectYIndexed),
opcode::eor::X_INDEXED_INDIRECT => (Eor, XIndexedIndirect),
opcode::eor::ZERO_PAGE => (Eor, ZeroPage),
opcode::eor::ZERO_PAGE_X_INDEXED => (Eor, ZeroPageXIndexed),
opcode::ign::unofficial0::ABSOLUTE => (Ign, Absolute),
opcode::ign::unofficial0::ABSOLUTE_X_INDEXED => (Ign, AbsoluteXIndexed),
opcode::ign::unofficial0::ZERO_PAGE => (Ign, ZeroPage),
opcode::ign::unofficial0::ZERO_PAGE_X_INDEXED => (Ign, ZeroPageXIndexed),
opcode::ign::unofficial1::ABSOLUTE_X_INDEXED => (Ign, AbsoluteXIndexed),
opcode::ign::unofficial1::ZERO_PAGE => (Ign, ZeroPage),
opcode::ign::unofficial1::ZERO_PAGE_X_INDEXED => (Ign, ZeroPageXIndexed),
opcode::ign::unofficial2::ABSOLUTE_X_INDEXED => (Ign, AbsoluteXIndexed),
opcode::ign::unofficial2::ZERO_PAGE => (Ign, ZeroPage),
opcode::ign::unofficial2::ZERO_PAGE_X_INDEXED => (Ign, ZeroPageXIndexed),
opcode::ign::unofficial3::ABSOLUTE_X_INDEXED => (Ign, AbsoluteXIndexed),
opcode::ign::unofficial3::ZERO_PAGE_X_INDEXED => (Ign, ZeroPageXIndexed),
opcode::ign::unofficial4::ABSOLUTE_X_INDEXED => (Ign, AbsoluteXIndexed),
opcode::ign::unofficial4::ZERO_PAGE_X_INDEXED => (Ign, ZeroPageXIndexed),
opcode::ign::unofficial5::ABSOLUTE_X_INDEXED => (Ign, AbsoluteXIndexed),
opcode::ign::unofficial5::ZERO_PAGE_X_INDEXED => (Ign, ZeroPageXIndexed),
opcode::inc::ABSOLUTE => (Inc, Absolute),
opcode::inc::ABSOLUTE_X_INDEXED => (Inc, AbsoluteXIndexed),
opcode::inc::ZERO_PAGE => (Inc, ZeroPage),
opcode::inc::ZERO_PAGE_X_INDEXED => (Inc, ZeroPageXIndexed),
opcode::inx::IMPLIED => (Inx, Implied),
opcode::iny::IMPLIED => (Iny, Implied),
opcode::isc::unofficial0::X_INDEXED_INDIRECT => (Isc, XIndexedIndirect),
opcode::isc::unofficial0::ZERO_PAGE => (Isc, ZeroPage),
opcode::isc::unofficial0::ABSOLUTE => (Isc, Absolute),
opcode::isc::unofficial0::INDIRECT_Y_INDEXED => (Isc, IndirectYIndexed),
opcode::isc::unofficial0::ZERO_PAGE_X_INDEXED => (Isc, ZeroPageXIndexed),
opcode::isc::unofficial0::ABSOLUTE_X_INDEXED => (Isc, AbsoluteXIndexed),
opcode::isc::unofficial0::ABSOLUTE_Y_INDEXED => (Isc, AbsoluteYIndexed),
opcode::jmp::ABSOLUTE => (Jmp, Absolute),
opcode::jmp::INDIRECT => (Jmp, Indirect),
opcode::jsr::ABSOLUTE => (Jsr, Absolute),
opcode::lax::unofficial0::ABSOLUTE => (Lax, Absolute),
opcode::lax::unofficial0::ABSOLUTE_Y_INDEXED => (Lax, AbsoluteYIndexed),
opcode::lax::unofficial0::IMMEDIATE => (Lax, Immediate),
opcode::lax::unofficial0::X_INDEXED_INDIRECT => (Lax, XIndexedIndirect),
opcode::lax::unofficial0::INDIRECT_Y_INDEXED => (Lax, IndirectYIndexed),
opcode::lax::unofficial0::ZERO_PAGE => (Lax, ZeroPage),
opcode::lax::unofficial0::ZERO_PAGE_Y_INDEXED => (Lax, ZeroPageYIndexed),
opcode::lda::ABSOLUTE => (Lda, Absolute),
opcode::lda::ABSOLUTE_X_INDEXED => (Lda, AbsoluteXIndexed),
opcode::lda::ABSOLUTE_Y_INDEXED => (Lda, AbsoluteYIndexed),
opcode::lda::IMMEDIATE => (Lda, Immediate),
opcode::lda::INDIRECT_Y_INDEXED => (Lda, IndirectYIndexed),
opcode::lda::X_INDEXED_INDIRECT => (Lda, XIndexedIndirect),
opcode::lda::ZERO_PAGE => (Lda, ZeroPage),
opcode::lda::ZERO_PAGE_X_INDEXED => (Lda, ZeroPageXIndexed),
opcode::ldx::ABSOLUTE => (Ldx, Absolute),
opcode::ldx::ABSOLUTE_Y_INDEXED => (Ldx, AbsoluteYIndexed),
opcode::ldx::IMMEDIATE => (Ldx, Immediate),
opcode::ldx::ZERO_PAGE => (Ldx, ZeroPage),
opcode::ldx::ZERO_PAGE_Y_INDEXED => (Ldx, ZeroPageYIndexed),
opcode::ldy::ABSOLUTE => (Ldy, Absolute),
opcode::ldy::ABSOLUTE_X_INDEXED => (Ldy, AbsoluteXIndexed),
opcode::ldy::IMMEDIATE => (Ldy, Immediate),
opcode::ldy::ZERO_PAGE => (Ldy, ZeroPage),
opcode::ldy::ZERO_PAGE_X_INDEXED => (Ldy, ZeroPageXIndexed),
opcode::lsr::ABSOLUTE => (Lsr, Absolute),
opcode::lsr::ABSOLUTE_X_INDEXED => (Lsr, AbsoluteXIndexed),
opcode::lsr::ACCUMULATOR => (Lsr, Accumulator),
opcode::lsr::ZERO_PAGE => (Lsr, ZeroPage),
opcode::lsr::ZERO_PAGE_X_INDEXED => (Lsr, ZeroPageXIndexed),
opcode::nop::IMPLIED => (Nop, Implied),
opcode::nop::unofficial0::IMPLIED => (Nop, Implied),
opcode::nop::unofficial1::IMPLIED => (Nop, Implied),
opcode::nop::unofficial2::IMPLIED => (Nop, Implied),
opcode::nop::unofficial3::IMPLIED => (Nop, Implied),
opcode::nop::unofficial4::IMPLIED => (Nop, Implied),
opcode::nop::unofficial5::IMPLIED => (Nop, Implied),
opcode::ora::ABSOLUTE => (Ora, Absolute),
opcode::ora::ABSOLUTE_X_INDEXED => (Ora, AbsoluteXIndexed),
opcode::ora::ABSOLUTE_Y_INDEXED => (Ora, AbsoluteYIndexed),
opcode::ora::IMMEDIATE => (Ora, Immediate),
opcode::ora::INDIRECT_Y_INDEXED => (Ora, IndirectYIndexed),
opcode::ora::X_INDEXED_INDIRECT => (Ora, XIndexedIndirect),
opcode::ora::ZERO_PAGE => (Ora, ZeroPage),
opcode::ora::ZERO_PAGE_X_INDEXED => (Ora, ZeroPageXIndexed),
opcode::pha::IMPLIED => (Pha, Implied),
opcode::php::IMPLIED => (Php, Implied),
opcode::pla::IMPLIED => (Pla, Implied),
opcode::plp::IMPLIED => (Plp, Implied),
opcode::rla::unofficial0::X_INDEXED_INDIRECT => (Rla, XIndexedIndirect),
opcode::rla::unofficial0::ZERO_PAGE => (Rla, ZeroPage),
opcode::rla::unofficial0::ABSOLUTE => (Rla, Absolute),
opcode::rla::unofficial0::INDIRECT_Y_INDEXED => (Rla, IndirectYIndexed),
opcode::rla::unofficial0::ZERO_PAGE_X_INDEXED => (Rla, ZeroPageXIndexed),
opcode::rla::unofficial0::ABSOLUTE_X_INDEXED => (Rla, AbsoluteXIndexed),
opcode::rla::unofficial0::ABSOLUTE_Y_INDEXED => (Rla, AbsoluteYIndexed),
opcode::rol::ABSOLUTE => (Rol, Absolute),
opcode::rol::ABSOLUTE_X_INDEXED => (Rol, AbsoluteXIndexed),
opcode::rol::ACCUMULATOR => (Rol, Accumulator),
opcode::rol::ZERO_PAGE => (Rol, ZeroPage),
opcode::rol::ZERO_PAGE_X_INDEXED => (Rol, ZeroPageXIndexed),
opcode::ror::ABSOLUTE => (Ror, Absolute),
opcode::ror::ABSOLUTE_X_INDEXED => (Ror, AbsoluteXIndexed),
opcode::ror::ACCUMULATOR => (Ror, Accumulator),
opcode::ror::ZERO_PAGE => (Ror, ZeroPage),
opcode::ror::ZERO_PAGE_X_INDEXED => (Ror, ZeroPageXIndexed),
opcode::rra::unofficial0::X_INDEXED_INDIRECT => (Rra, XIndexedIndirect),
opcode::rra::unofficial0::ZERO_PAGE => (Rra, ZeroPage),
opcode::rra::unofficial0::ABSOLUTE => (Rra, Absolute),
opcode::rra::unofficial0::INDIRECT_Y_INDEXED => (Rra, IndirectYIndexed),
opcode::rra::unofficial0::ZERO_PAGE_X_INDEXED => (Rra, ZeroPageXIndexed),
opcode::rra::unofficial0::ABSOLUTE_X_INDEXED => (Rra, AbsoluteXIndexed),
opcode::rra::unofficial0::ABSOLUTE_Y_INDEXED => (Rra, AbsoluteYIndexed),
opcode::rti::IMPLIED => (Rti, Implied),
opcode::rts::IMPLIED => (Rts, Implied),
opcode::sax::unofficial0::X_INDEXED_INDIRECT => (Sax, XIndexedIndirect),
opcode::sax::unofficial0::ZERO_PAGE => (Sax, ZeroPage),
opcode::sax::unofficial0::ABSOLUTE => (Sax, Absolute),
opcode::sax::unofficial0::ZERO_PAGE_Y_INDEXED => (Sax, ZeroPageYIndexed),
opcode::sbc::ABSOLUTE => (Sbc, Absolute),
opcode::sbc::ABSOLUTE_X_INDEXED => (Sbc, AbsoluteXIndexed),
opcode::sbc::ABSOLUTE_Y_INDEXED => (Sbc, AbsoluteYIndexed),
opcode::sbc::IMMEDIATE => (Sbc, Immediate),
opcode::sbc::INDIRECT_Y_INDEXED => (Sbc, IndirectYIndexed),
opcode::sbc::X_INDEXED_INDIRECT => (Sbc, XIndexedIndirect),
opcode::sbc::ZERO_PAGE => (Sbc, ZeroPage),
opcode::sbc::ZERO_PAGE_X_INDEXED => (Sbc, ZeroPageXIndexed),
opcode::sbc::unofficial0::IMMEDIATE => (Sbc, Immediate),
opcode::sec::IMPLIED => (Sec, Implied),
opcode::sed::IMPLIED => (Sed, Implied),
opcode::sei::IMPLIED => (Sei, Implied),
opcode::skb::unofficial0::IMMEDIATE => (Skb, Immediate),
opcode::skb::unofficial1::IMMEDIATE => (Skb, Immediate),
opcode::skb::unofficial2::IMMEDIATE => (Skb, Immediate),
opcode::skb::unofficial3::IMMEDIATE => (Skb, Immediate),
opcode::skb::unofficial4::IMMEDIATE => (Skb, Immediate),
opcode::slo::unofficial0::X_INDEXED_INDIRECT => (Slo, XIndexedIndirect),
opcode::slo::unofficial0::ZERO_PAGE => (Slo, ZeroPage),
opcode::slo::unofficial0::ABSOLUTE => (Slo, Absolute),
opcode::slo::unofficial0::INDIRECT_Y_INDEXED => (Slo, IndirectYIndexed),
opcode::slo::unofficial0::ZERO_PAGE_X_INDEXED => (Slo, ZeroPageXIndexed),
opcode::slo::unofficial0::ABSOLUTE_X_INDEXED => (Slo, AbsoluteXIndexed),
opcode::slo::unofficial0::ABSOLUTE_Y_INDEXED => (Slo, AbsoluteYIndexed),
opcode::sre::unofficial0::X_INDEXED_INDIRECT => (Sre, XIndexedIndirect),
opcode::sre::unofficial0::ZERO_PAGE => (Sre, ZeroPage),
opcode::sre::unofficial0::ABSOLUTE => (Sre, Absolute),
opcode::sre::unofficial0::INDIRECT_Y_INDEXED => (Sre, IndirectYIndexed),
opcode::sre::unofficial0::ZERO_PAGE_X_INDEXED => (Sre, ZeroPageXIndexed),
opcode::sre::unofficial0::ABSOLUTE_X_INDEXED => (Sre, AbsoluteXIndexed),
opcode::sre::unofficial0::ABSOLUTE_Y_INDEXED => (Sre, AbsoluteYIndexed),
opcode::sta::ABSOLUTE => (Sta, Absolute),
opcode::sta::ABSOLUTE_X_INDEXED => (Sta, AbsoluteXIndexed),
opcode::sta::ABSOLUTE_Y_INDEXED => (Sta, AbsoluteYIndexed),
opcode::sta::INDIRECT_Y_INDEXED => (Sta, IndirectYIndexed),
opcode::sta::X_INDEXED_INDIRECT => (Sta, XIndexedIndirect),
opcode::sta::ZERO_PAGE => (Sta, ZeroPage),
opcode::sta::ZERO_PAGE_X_INDEXED => (Sta, ZeroPageXIndexed),
opcode::stx::ABSOLUTE => (Stx, Absolute),
opcode::stx::ZERO_PAGE => (Stx, ZeroPage),
opcode::stx::ZERO_PAGE_Y_INDEXED => (Stx, ZeroPageYIndexed),
opcode::sty::ABSOLUTE => (Sty, Absolute),
opcode::sty::ZERO_PAGE => (Sty, ZeroPage),
opcode::sty::ZERO_PAGE_X_INDEXED => (Sty, ZeroPageXIndexed),
opcode::sxa::unofficial0::ABSOLUTE_Y_INDEXED => (Sxa, AbsoluteYIndexed),
opcode::sya::unofficial0::ABSOLUTE_X_INDEXED => (Sya, AbsoluteXIndexed),
opcode::tax::IMPLIED => (Tax, Implied),
opcode::tay::IMPLIED => (Tay, Implied),
opcode::tsx::IMPLIED => (Tsx, Implied),
opcode::txa::IMPLIED => (Txa, Implied),
opcode::txs::IMPLIED => (Txs, Implied),
opcode::tya::IMPLIED => (Tya, Implied),
_ => return Err(UnknownOpcode(opcode)),
};
Ok(Instruction::new(instruction_type, addressing_mode))
}
pub fn instruction_type(&self) -> InstructionType {
self.instruction_type
}
pub fn addressing_mode(&self) -> AddressingMode {
self.addressing_mode
}
}
#[derive(Debug, Clone)]
pub struct InstructionWithOperand {
address: Address,
instruction: Instruction,
operand: Vec<u8>,
}
impl InstructionWithOperand {
pub fn decode<M: MemoryReadOnly>(address: Address, memory: &M) -> Result<Self, UnknownOpcode> {
let opcode = memory.read_u8_read_only(address);
let instruction = Instruction::from_opcode(opcode)?;
let operand_bytes = instruction.addressing_mode.operand_bytes();
let mut operand = Vec::new();
for i in 0..operand_bytes {
operand
.push(memory.read_u8_read_only(address.wrapping_add(i as Address).wrapping_add(1)));
}
Ok(Self {
address,
instruction,
operand,
})
}
pub fn next<M: MemoryReadOnly>(cpu: &Cpu, memory: &M) -> Result<Self, UnknownOpcode> {
Self::decode(cpu.pc, memory)
}
pub fn instruction(&self) -> Instruction {
self.instruction
}
pub fn operand_u16_le(&self) -> Option<u16> {
match self.operand.as_slice() {
&[_x] => None,
&[x0, x1] => Some((x1 as u16) << 8 | x0 as u16),
_ => None,
}
}
pub fn address(&self) -> Address {
self.address
}
}
impl fmt::Display for InstructionWithOperand {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{:04X} {:?}({:?}) ",
self.address, self.instruction.instruction_type, self.instruction.addressing_mode
)?;
match self.operand.as_slice() {
&[x] => write!(f, "{:02X}", x)?,
&[x0, x1] => write!(f, "{:04X}", (x1 as u16) << 8 | x0 as u16)?,
_ => (),
}
Ok(())
}
}