C6-Reticulum-ASM/tests/boot/test__init_data.py

63 lines
2.7 KiB
Python
Raw Permalink Normal View History

"""Tests for src/boot/_init_data.S.
Static disassembly checks (per @verify: kat-only). On qemu-virt the
function is semantically identity (LMA == VMA), but the asm shape load,
store, increment-both, branch is the same as on the C6 where it
performs a real flash SRAM copy. The tests assert the shape; the
integration check (a non-zero .data initialiser observed at runtime)
lands when _main wires up the boot chain.
"""
from __future__ import annotations
import re
import pytest
from harness import build
@pytest.fixture(scope="module")
def artifacts() -> build.BuildArtifacts:
return build.build("qemu-virt")
def test_loads_three_bounds(artifacts: build.BuildArtifacts) -> None:
"""Three la pairs at the head: __data_start, __data_end, __data_load_start."""
body = build.objdump_disassemble(artifacts.elf, symbol="_init_data")
instrs = [line for line in body.splitlines() if re.match(r"^\s*[0-9a-f]{8}:", line)]
assert len(instrs) >= 9, body
for i, reg in enumerate(("t0", "t1", "t2")):
assert "auipc" in instrs[2 * i] and f"{reg}," in instrs[2 * i], instrs[2 * i]
assert "addi" in instrs[2 * i + 1] and f"{reg}," in instrs[2 * i + 1], instrs[2 * i + 1]
def test_load_store_word_pair(artifacts: build.BuildArtifacts) -> None:
body = build.objdump_disassemble(artifacts.elf, symbol="_init_data")
# The word load is from the LMA cursor (t2), the word store goes to the
# VMA cursor (t0). Match the canonical forms; objdump may compress.
assert re.search(r"\blw\b\s+t3,0\(t2\)", body), body
assert re.search(r"\bsw\b\s+t3,0\(t0\)", body), body
def test_loop_advances_both_cursors(artifacts: build.BuildArtifacts) -> None:
body = build.objdump_disassemble(artifacts.elf, symbol="_init_data")
# Two `addi … 4` increments per iteration — one for t0, one for t2.
addi_count = len(re.findall(r"\baddi\s+(t0|t2),", body)) + \
len(re.findall(r"\baddi\s+(t0|t2),", body))
# The la prologue also uses addi for low-12-bit fixups; subtract the
# known three la pairs (3 addi). Increments contribute 2 more.
addi_total = len(re.findall(r"\baddi\b", body))
assert addi_total >= 5, body # 3 (la fixups) + 2 (increments)
def test_function_returns(artifacts: build.BuildArtifacts) -> None:
body = build.objdump_disassemble(artifacts.elf, symbol="_init_data")
assert "ret" in body or "jalr\tzero" in body, body
def test_does_not_touch_callee_saved(artifacts: build.BuildArtifacts) -> None:
body = build.objdump_disassemble(artifacts.elf, symbol="_init_data")
for match in re.findall(r"\b(s\d+)\b,", body):
pytest.fail(f"_init_data writes callee-saved register {match}: {body}")