188. Flags handler interrupt and break flags

add I, B, and unused-bit flag helpers.

Lesson 188 of 356 · tests/chapter_01_cpu/test_188_flags_handler_interrupt_and_break_flags.py

In this step, define Break as bit 4 and the pushed-status unused bit as bit 5. Add to `emulator/cpu/flags_handler.py`:

INTERRUPT_FLAG = 1 << 2
B_FLAG = 1 << 4
ONE_FLAG = 1 << 5

def set_interrupt_disable_flag(self, enabled: bool):
    if enabled:
        self.cpu.p |= INTERRUPT_FLAG
    else:
        self.cpu.p &= ~INTERRUPT_FLAG

def set_break_flag(self, enabled: bool):
    if enabled:
        self.cpu.p |= B_FLAG
    else:
        self.cpu.p &= ~B_FLAG

def set_one_flag(self, enabled: bool):
    if enabled:
        self.cpu.p |= ONE_FLAG
    else:
        self.cpu.p &= ~ONE_FLAG

def get_interrupt_disable_flag(self) -> bool:
    return bool(self.cpu.p & INTERRUPT_FLAG)

def get_break_flag(self) -> bool:
    return bool(self.cpu.p & B_FLAG)

def get_one_flag(self) -> bool:
    return bool(self.cpu.p & ONE_FLAG)

Why this step exists

We are preparing to implement BRK.

BRK is a software interrupt instruction. To implement it clearly, the CPU needs helpers for two status flags:

I flag -> Interrupt Disable, bit 2
B flag -> Break, bit 4
ONE flag -> unused/status bit 5 used in pushed status bytes

BRK will need them because

  • it sets the Interrupt Disable flag after entering the interrupt handler
  • it pushes a status byte with the Break flag set

Design goal

Keep bit manipulation inside FlagsHandler instead of spreading raw cpu.p bit operations through instruction code.

Important terminology

Interrupt Disable flag:
    When set, maskable IRQ interrupts are disabled.

Break flag:
    Used to mark that the pushed status byte came from BRK.

Common mistake

Do not confuse the BRK opcode with the Break flag.

BRK opcode: 0x00, the instruction byte in memory
B flag:     bit 4 inside the status byte pushed to the stack
ONE flag:   bit 5, usually set in pushed status bytes

Rationale: named setters centralize independent read-modify-write operations on P and getters expose booleans. Invariants: each setter changes only its bit; I, B, ONE, and all existing flags remain independent. Misconception: B and the always-one pushed-status bit are not the same bit, and opcode $00 is neither.

Out of scope: this step does not implement BRK or decide when bits are set; those are steps 189-190. RTI/PHP/PLP, NMI behavior, and CPU stack helpers remain later work.

Run this lesson

uv run pytest tests/chapter_01_cpu/test_188_flags_handler_interrupt_and_break_flags.py -v