use super::Cpu;
use super::{pack_bytes, unpack_bytes};
use crate::processor_status::ProcessorStatus;
use crate::IRQ_BRK_VECTOR_ADDRESS;
use crate::{Interrupts, RESET_VECTOR_ADDRESS};
use crate::{Mapper, NMI_VECTOR_ADDRESS};
#[derive(PartialEq, Debug, Clone, Copy)]
pub(crate) enum InterruptState {
Inactive,
Reset,
MaskableInterrupt,
NonMaskableInterrupt,
}
impl<M: Mapper, I: Interrupts> Cpu<M, I> {
pub(crate) fn instruction_brk(&mut self, interrupt_state: InterruptState) -> u8 {
let (pc_low, pc_high) = unpack_bytes(self.program_counter);
self.push(pc_high);
self.push(pc_low);
if interrupt_state == InterruptState::Inactive || interrupt_state == InterruptState::Reset {
self.processor_status.set_break_flag();
}
self.push(self.processor_status.0);
if interrupt_state == InterruptState::Inactive || interrupt_state == InterruptState::Reset {
self.processor_status.clear_break_flag();
}
self.processor_status.set_interrupt_disable_flag();
self.program_counter = match interrupt_state {
InterruptState::Inactive | InterruptState::MaskableInterrupt => pack_bytes(
self.read(IRQ_BRK_VECTOR_ADDRESS),
self.read(IRQ_BRK_VECTOR_ADDRESS + 1),
),
InterruptState::Reset => pack_bytes(
self.read(RESET_VECTOR_ADDRESS),
self.read(RESET_VECTOR_ADDRESS + 1),
),
InterruptState::NonMaskableInterrupt => pack_bytes(
self.read(NMI_VECTOR_ADDRESS),
self.read(NMI_VECTOR_ADDRESS + 1),
),
};
7
}
pub(crate) fn instruction_nop(&mut self) -> u8 {
2
}
pub(crate) fn instruction_rti(&mut self) -> u8 {
self.processor_status =
ProcessorStatus((self.pop() & 0b1100_1111) | (self.processor_status.0 & 0b0011_0000));
let pc_low = self.pop();
let pc_high: u8 = self.pop();
self.program_counter = pack_bytes(pc_low, pc_high);
6
}
}