197. Instrucción php

implementar el comportamiento de PHP.

Lección 197 de 356 · tests/chapter_01_cpu/test_197_instruction_php.py

En este paso, modifica únicamente `emulator/cpu/instructions.py añadiendo php(cpu). Requisito previo: FlagsHandler.set_break_flag` ya existe.

Por qué existe este paso

PHP apila P con la marca Break del emulador activada y después borra esa marca transitoria del estado real de la CPU. Como en todo push, escribe en $0100 | S antes de decrementar el S de 8 bits.

Implementación sugerida

def php(cpu: CPU):
    cpu.flags.set_break_flag(True)
    cpu.flags.set_one_flag(True)
    cpu.bus.write(STACK_BASE | cpu.s, cpu.p)
    cpu.flags.set_break_flag(False)
    cpu.flags.set_one_flag(False)
    cpu.s = (cpu.s - 1) & 0xFF

Invariantes: conserva todos los bits de estado preexistentes; activa Break y ONE en la copia apilada; borra ambos del P real después; escribe antes de decrementar y ajusta S; no derives Z ni N a partir del byte de estado.

Concepto erróneo: Break no queda activado en `cpu.p` tras PHP solo porque esté activado en el byte escrito en la pila.

Fuera de alcance: el registro del opcode $08 corresponde al paso 198. Cualquier cambio posterior a las reglas del byte de estado apilado corresponde a sus propios pasos numerados.

Ejecutar esta lección

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