109. Instruction ror

implement memory-targeted ROR.

Lesson 109 of 356 · tests/chapter_01_cpu/test_109_instruction_ror.py

In this step, after lessons 102-108 complete ROL, add only the ROR memory primitive. ROR opcode wiring belongs to lessons 111-115.

Complete example implementation in the production location

`emulator/cpu/instructions.py::ror`::

def ror(cpu: CPU, addr: int):
    value = cpu.bus.read(addr)
    old_carry = int(cpu.flags.get_carry_flag())

    result = (value >> 1) | (old_carry << 7)
    result_8 = result & 0xFF

    # Set flags

    cpu.flags.set_carry_flag((value & 0x1) != 0)
    cpu.flags.set_zero_flag(result_8 == 0)
    cpu.flags.set_negative_flag((result_8 & 0b1000_0000) != 0)

    cpu.bus.write(addr, result_8)

Why this step exists

A single addressing-independent memory primitive supplies every later ROR addressing mode with identical read/modify/write semantics.

Invariants: sample Carry before flags change; old Carry enters bit 7, original bit 0 becomes Carry, result is eight-bit, and Z/N derive from the stored result. Exactly the addressed memory byte changes; A does not.

Misconception: ROR is not LSR. LSR inserts zero at bit 7, whereas ROR inserts old Carry; Carry cannot be derived from the shifted result.

Out of scope: accumulator ROR is lesson 110, opcode/addressing wiring is 111-115, and cycle-level bus sequencing is later work.

Run this lesson

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