Skip to main content

rustynes_cpu/
status.rs

1//! Status register flags for the 6502.
2//!
3//! Per `docs/cpu-6502.md` §State, the bits are: N V _ B D I Z C from MSB to
4//! LSB. Bit 5 (`U`) is unused on real hardware but always reads as 1; we
5//! set it on power-on to match. The B flag exists only on stack pushes
6//! (PHP / BRK push it set; IRQ/NMI sequences push it clear).
7
8use bitflags::bitflags;
9
10bitflags! {
11    /// Processor status flags. Bits match the layout pushed onto the stack.
12    #[derive(Debug, Clone, Copy, Eq, PartialEq)]
13    pub struct Status: u8 {
14        /// Carry.
15        const CARRY = 0b0000_0001;
16        /// Zero.
17        const ZERO = 0b0000_0010;
18        /// IRQ disable.
19        const INTERRUPT_DISABLE = 0b0000_0100;
20        /// Decimal mode (settable on 2A03 but ignored arithmetically).
21        const DECIMAL = 0b0000_1000;
22        /// Break flag (only meaningful on stack pushes).
23        const BREAK = 0b0001_0000;
24        /// Unused bit (always reads 1).
25        const UNUSED = 0b0010_0000;
26        /// Overflow.
27        const OVERFLOW = 0b0100_0000;
28        /// Negative.
29        const NEGATIVE = 0b1000_0000;
30    }
31}
32
33impl Status {
34    /// Power-on state: I and U set, others clear (bit pattern `$24`).
35    #[must_use]
36    pub const fn power_on() -> Self {
37        Self::from_bits_truncate(0x24)
38    }
39
40    /// Set N and Z based on `value`. Used by every load/transfer/arith op
41    /// that produces a result observable by the program.
42    pub fn set_nz(&mut self, value: u8) {
43        self.set(Self::ZERO, value == 0);
44        self.set(Self::NEGATIVE, value & 0x80 != 0);
45    }
46}