test/asm — assembler / disassembler corpus
File-driven test harness for kit's asm front end and matching
disassembler. Companion to doc/ASM.md; see phase 1 there for the
current state.
Layout
Three sub-directories, one per static-output asm-runner mode. The
shell driver (run.sh) walks them by suffix.
| sub-dir | input | goldens | drives |
|---|---|---|---|
encode/ |
<name>.s |
<name>.expected.hex (H) |
H, D, J, E |
<name>.expected (D/J/E exit) |
|||
decode/ |
<name>.hex |
<name>.expected.txt |
T |
listing/ |
<name>.in.bin |
<name>.expected.lst |
L |
Paths
Default matrix HTLDJE:
H— Hex encode roundtrip.asm-runner --encode IN.sdumps.textbytes as lowercase hex; diff vs<name>.expected.hex. Drives the encoder against a known-good byte sequence.T— Text decode.asm-runner --decode IN.hexwalks the bytes throughkit_disasm_iter_*, one instruction per line; diff vs<name>.expected.txt.L— Listing.asm-runner --listing IN.in.binrunskit_obj_disasmagainst the ELF; diff vs<name>.expected.lst.D— Direct JIT.asm-runner --jit IN.sparses, JIT-links, and callstest_main; exit code matches<name>.expected. No file I/O. Host arch must match the cross-target.J— JIT via file.asm-runner --emit+jit-runneron the resulting.o. Same expected exit code as D. Exercises elf_emit / elf_read fidelity on asm-produced objects.E— ELF exec.asm-runner --emit+link-exe-runner+ start.o, run under qemu/podman pertest/lib/exec_target.sh. Cross-host friendly.
Cases without a <name>.expected sidecar skip D/J/E silently — the
encode/decode/listing goldens stand alone and don't always make sense
to execute (e.g. nop; ret falls off the end of _start).
The encode case's .s file must define a test_main global for D/J/E
to be meaningful — start.c calls test_main and uses its return value
as the exit code, mirroring the test/parse and test/cg conventions.
Sidecars
<name>.expected— integer exit code; consumed by D/J/E. Absent → those paths skip.<name>.expected.hex— golden bytes for H.<name>.expected.txt— golden decode text for T.<name>.expected.lst— golden listing for L.<name>.skip— single-line reason. The case is reported as SKIP for every path it applies to. Every phase-1 case carries one because the underlying APIs (asm_parse,kit_disasm_iter_*,kit_obj_disasm) are still stubs. They drop as the matching subsystems land.
Goldens
Goldens are checked in. regen.sh documents how to refresh them from
the host as / objdump; it is committed as a maintainer aid and not
run by CI. The phase-1 smoke set is intentionally tiny — one case per
sub-dir — because nothing exercises the goldens yet. Coverage expands
alongside phases 3 and 4 in doc/ASM.md §5.
Naming convention
Cases are named <concept>[_<variant>] (e.g. exit_zero, nop_ret,
mov_imm_w0). When a case targets a specific encoding family, prefix
with the AArch64 spec section ID (6_4_2_03_*) so the corpus stays
grouped by spec topic, matching the pattern already used in
test/parse/cases/.