mirror of
https://github.com/ratspeak/C6-Reticulum-ASM
synced 2026-08-12 18:07:18 -04:00
log_init is a single ret today; the ts source lands when clock_get_freq is wired and log_event needs a real ms-since-boot value. The function exists now so log_event can call it without forward dependency. log_str tail-calls uart_tx_bytes — no frame, ra threads through. The indirection exists so log_event and downstream primitives don't couple to the underlying TX implementation; a future IRQ-driven uart_tx_bytes swap stays local to one file.
38 lines
1.3 KiB
Python
38 lines
1.3 KiB
Python
"""Tests for src/log/log_str.S — tail-call into uart_tx_bytes."""
|
|
|
|
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_function_exists(artifacts: build.BuildArtifacts) -> None:
|
|
assert build.symbol_address(artifacts.elf, "log_str") > 0
|
|
|
|
|
|
def test_tail_calls_uart_tx_bytes(artifacts: build.BuildArtifacts) -> None:
|
|
"""Body is a single tail-call: auipc/jalr to uart_tx_bytes (no frame
|
|
setup, no ra save). The target symbol comment must reference
|
|
uart_tx_bytes."""
|
|
body = build.objdump_disassemble(artifacts.elf, symbol="log_str")
|
|
instrs = [line for line in body.splitlines() if re.match(r"^\s*[0-9a-f]{8}:", line)]
|
|
# `tail uart_tx_bytes` → auipc t1, ... ; jalr zero, off(t1) (or jr).
|
|
# Compressed forms are also possible (`c.j`, `c.jr`).
|
|
assert "uart_tx_bytes" in body, body
|
|
# No stack adjust: no `addi sp, sp, …` should appear.
|
|
for line in instrs:
|
|
assert not re.search(r"\baddi\s+sp", line), line
|
|
|
|
|
|
def test_no_callee_saved_writes(artifacts: build.BuildArtifacts) -> None:
|
|
body = build.objdump_disassemble(artifacts.elf, symbol="log_str")
|
|
for match in re.findall(r"\b(s\d+)\b,", body):
|
|
pytest.fail(f"log_str writes callee-saved {match}: {body}")
|