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}