Why a census and not a walk
CLAUDE.md's rule that a first-failure census ranks by queue position applies to
the compiler's own error reporting just as much as to a corpus probe: attempting
SDL2/SDL.h reports ONE unsupported instruction, so clearing it reveals the
next and nothing tells you how many are left. Grepping the headers gives the
whole population in one command, and the population is small and closed:
| mnemonic | reached on x86-64? |
|---|---|
xchgb (with %b0/%h0, =Q) |
yes — landed 642943118 |
bswapl, bswapq |
yes — this ticket |
pause |
yes — this ticket |
int $3 |
yes — this ticket |
rlwimi, or 27,27,27 |
no, ppc |
dmb, mcr, bkpt, brk |
no, arm / aarch64 |
ebreak |
no, riscv |
rorw |
already supported |
What landed
x64_bswap_reg(size, reg)inx64enc.inc. The register rides in the OPCODE (0F C8+rd), not a ModRM byte, so REX.B is the only thing naming a register above 7 — and a dropped prefix does not fail to assemble, it swaps a DIFFERENT register. Behind the sharedEncPrefixAndREXfunnel for exactly the reason the%h0fix documents: 58 of its 60 call sites reach it directly, and a second prefix decision beside it is the wrong-layer bug.- 16-bit
bswapis refused. It assembles and Intel documents it as UNDEFINED, so the one width a caller might reach for by analogy is the one that silently produces a wrong runtime answer. Verified the refusal fires. pause=F3 90inasmenc.inc, named separately fromnopbecause the prefix IS the instruction.int $3=CC, matching whatasemits.
Guards, and what each can actually see
test/test_x64enc.pas: four bswap rows againstas, paired so that each pair differs in exactly one bit — reg 0 vs 15 at one width isolates REX.B, 32 vs 64 at one register isolates REX.W.test/casm_bswap_and_pause.c: values against gcc on identical source.- The pause prefix is a paired byte delta in the Makefile (
F3 90, 0 -> 1), because the value rows cannot see it: a bare nop is a legal implementation of pause and the loop still counts to 7. test/casm_int3_traps.c: the assertion is the SIGTRAP, and the row's sense is inverted — a clean exit is the failure.
Three instruments that lied, all correct about something else
objdump -dparses ZERO instructions out of a pxx binary. It reported "no bswap present" for a binary containing three, which reads exactly like the feature being absent.- A CC byte count said
int $3emitted nothing. With- and without-asm binaries came out at identical size with identical CC counts — CC is the padding filler — while one traps and the other exits clean. - The pause guard, written to demonstrate framing, was itself unframed.
od | tr -d ' \n'runs the hex together, sof390matched ACROSS two adjacent bytes and the CONTROL binary answered 2 where the truth is 0.
The i386 sibling is NOT covered, deliberately and loudly
AttKnows386 does not list these and asmtext_386.inc cannot assemble them,
so the i386 arm fails with unsupported instruction rather than emitting
nothing. That is checked, not assumed: AttEncodeOne errors on a False from
AttEmitInstr. SDL's i386 arm wants bswapl too, so this is a real gap —
named here rather than left for someone to discover, which is the lesson the
%h0 fix paid for.