You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add error-case ("negative test") coverage per the user's preferred
convention: rather than a separate source file, error-triggering
instruction lines are appended to the existing per-mnemonic .asm file
under a %ifdef ERROR guard, and the harness assembles the same file
twice -- once without -DERROR (existing positive-path coverage,
unaffected) and once with -DERROR (expected to fail, per nasm-t.py's
"error": "expected" json convention, matching the pre-existing
travis/ret/ret.json pattern).
The error material comes for free from lines the generator already
knows are bit-width-incompatible:
- Lines needing 64-bit encodings (reg64/imm64 operands, hireg r8-r15,
apxreg r16-r31, etc. -- %needs64_token / build_variant_line) are, by
construction, exactly the lines already excluded from the 16/32-bit
"narrow" body. They're appended to the narrow file under %ifdef
ERROR and probed at --bits 16/32 with -DERROR; only widths where the
block actually fails become json entries.
- Symmetrically, CALL/JMP near-indirect targets via rm16/rm32 (only
rm64 is valid in 64-bit mode -- confirmed empirically, matches the
NOLONG flag on those insns.xda templates) are appended to the full
(64-bit) body under %ifdef ERROR and probed at --bits 64 with
-DERROR.
Each candidate block is probed before being turned into a json entry,
so a line that unexpectedly *does* assemble at some width (this
generator doesn't model every mode restriction) doesn't turn into a
bogus "expected error" test; a mnemonic whose *only* surviving
coverage would be error entries is also rejected (see below), since
"this never assembles" isn't meaningful regression coverage on its
own.
While wiring this up, discovered and fixed two related bugs in the
existing branch-mnemonic handling (gen_operand()'s is_branch
substitution):
1. is_branch replaced *every* operand of a branch mnemonic with the
".L1" local-label text, not just genuine relative/near/short/abs
branch-displacement operands. This produced nonsensical lines like
"loop .L1, .L1" (LOOP's address-size-override form takes a fixed
"cx"/"ecx"/"rcx" second operand, not a branch target) and "call
.L1" for JMP/CALL's indirect (rm16/32/64) and far-pointer
(imm16:imm16) forms instead of an actual register/memory operand.
These bogus lines silently poisoned assembly for the whole
mnemonic, and LOOP/LOOPE/LOOPNE/LOOPNZ/LOOPZ/JCXZ were silently
dropped entirely as a result (present in the "16 dropped" list).
Restricting the substitution to base tokens matching
/^imm(?:8|16|32|64)$/ fixes both LOOP's operand and JMP/CALL's
indirect/far forms, and recovers all six previously-dropped
mnemonics with correct coverage.
2. Once (1) exposed genuine rm16/rm32 operand generation for CALL/JMP,
a new bit-width interaction appeared: rm16/rm32 near-indirect
targets are only valid in 16/32-bit mode (unlike ordinary reg16/32
operands elsewhere, which work at any bit width), so a line built
from one now broke 64-bit assembly for the whole mnemonic the same
way a needs64 line breaks 16/32-bit assembly. Added
branch_narrow_only() and a parallel avoid64 line flag (mirroring
needs64) to exclude these lines from the 64-bit "full" body -- this
is also what feeds the new symmetric 64-bit error-case coverage
described above.
Also added a safety-net to the existing "couldn't assemble in any
mode, drop the directory" check: a directory is now only kept if it
has at least one *non*-error json entry, preventing a future bug
symmetric to (1) from silently producing a directory whose only
content is error-case entries.
Verified via full scratch regeneration (2612 mnemonics generated / 10
dropped, up from 2606/16 thanks to the LOOP-family/JCXZ fix) +
nasm-t.py run (10918/10918 PASS, 0 FAIL) + per-mnemonic non-error
.json entry-count diff against the prior committed tree (identical
except the 6 newly-recovered mnemonics, confirming no regressions).
1976/2612 mnemonics gained at least one error-case entry (3951 error
json entries total). Regenerated travis/insns/ and validated via
'make -j32 travis' (all PASS, ~27s).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
0 commit comments