188. Manejador de flags de interrupción y de break

añadir los ayudantes para las flags I, B y el bit no usado.

Lección 188 de 356 · tests/chapter_01_cpu/test_188_flags_handler_interrupt_and_break_flags.py

En este paso, define Break como el bit 4 y el bit no usado del estado apilado como el bit 5. Añade a `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)

Por qué existe este paso

Nos estamos preparando para implementar BRK.

BRK es una instrucción de interrupción por software. Para implementarla con claridad, la CPU necesita ayudantes para dos flags de estado:

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

BRK las necesitará porque

  • activa la flag de Interrupt Disable después de entrar en el manejador de interrupción
  • apila un byte de estado con la flag de Break activada

Objetivo de diseño

Mantener la manipulación de bits dentro de FlagsHandler en lugar de repartir operaciones directas sobre los bits de cpu.p por todo el código de las instrucciones.

Terminología importante

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

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

Error común

No confundas el opcode BRK con la flag Break.

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

Justificación: los métodos de asignación con nombre centralizan operaciones independientes de lectura-modificación-escritura sobre P, y los métodos de lectura exponen valores booleanos. Invariantes: cada método de asignación cambia solo su bit; I, B, ONE y el resto de flags existentes permanecen independientes. Concepto erróneo: B y el bit siempre a uno del estado apilado no son el mismo bit, y el opcode $00 tampoco lo es.

Fuera de alcance: este paso no implementa BRK ni decide cuándo se activan los bits; eso son los pasos 189-190. RTI/PHP/PLP, el comportamiento de NMI, y los ayudantes de pila de la CPU quedan para trabajo posterior.

Ejecutar esta lección

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