197. 指令 php

实现 PHP 行为。

197 / 356 · tests/chapter_01_cpu/test_197_instruction_php.py

在本步骤中,只修改 `emulator/cpu/instructions.py,添加 php(cpu)。前置条件:FlagsHandler.set_break_flag` 已存在。

本步骤存在的原因

PHP 把带有模拟器 Break 标记置位的 P 压入栈,然后从当前 CPU 状态中清除这个临时标记。和所有入栈操作一样,它会先写入 $0100 | S,再递减这个 8 位的 S。

建议实现

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

不变量:保留所有原有的状态位;在压入栈的副本中置位 Break 和 ONE;之后从实时的 P 中清除这两位;先写入再递减,并对 S 做环绕处理;不要根据这个状态字节推导 Z 或 N。

常见误解:PHP 之后 `cpu.p` 中的 Break 位并不会因为压入栈的字节里置位了它,就一直保持启用状态。

范围之外:注册操作码 $08 属于第 198 步。日后对压栈状态字节规则的任何改动都属于它们各自的编号步骤。

运行本课

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