Even though NASM is now using 3.xx version numbers, I'm still the main
maintainer :)
2026-08-15 was my last day employed by Intel Corporation, so anything
since are not their copyright.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
It is a completely unimportant memory leak as the process is about to
exit, but it is easy to clean up.
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
During command line parsing, warning_state_init is NULL as the warning
stack is naturally not set up yet. Furthermore, -w* would mean return
to command-line default, which isn't even defined yet.
Rather than ignoring it or returning an error, do something useful by
allowing -w* to reset to the *compile time* default when specified on
the command line.
Reported-by: <momo-trip@github.com>
Fixes: https://github.com/netwide-assembler/nasm/issues/155
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
The idea of embedded warning documentation text in the source code was
a cute idea, but the resulting build dependency mess really made it
more painful than it was worth.
The warning declarations were moved to asm/warnings.dat quite a while
ago; remove stray note in the documentation.
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
win32_gs_help() looks up Ghostscript's install directory (GS_LIB) from
the registry and then tries to locate gswin64c.exe/gswin32c.exe/gs.exe
in it, but used File::Spec->catpath($p, $exe) to build the candidate
path. catpath() takes three arguments (volume, directory, file); called
with only two, $exe is interpreted as the directory and the file
component is left undef, so the result is just $exe on its own --
never a path that actually exists -- meaning the registry-based lookup
silently always failed and pspdf.pl fell back to a bare 'gs' on PATH
(which choco's ghostscript package does not add). Use catfile($p, $exe)
instead, which is the correct call for joining a directory and a
filename. Confirmed via real MSVC CI that Ghostscript is now found
purely from the registry, matching doc/source.src's documented
requirement that Ghostscript need not be on PATH.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The docs: target fed doc/Makefile.in directly to nmake, but that file
relies on several GNU make-only constructs nmake cannot parse at all:
the $^ automatic variable (not valid nmake macro syntax -- fatal
parse error), $< used outside of an inference rule (silently
unsupported, since nmake only defines $< within .SUFFIXES-style
rules), and the GNU-only "-include *.dep" optional wildcard include
directive (nmake only understands the unrelated "!include"
directive). Add tools/mkmsvcdocmak.pl, which rewrites just those
constructs to their explicit nmake-safe equivalents in a generated
copy (doc/Makefile.msvc), leaving doc/Makefile.in itself untouched for
the Unix/GNU make build. Verified by rewriting doc/Makefile.in this
way and building nasmdoc.pdf through it with GNU make standing in for
nmake.
Also, doc/Makefile.in expects doc/warnings.src, doc/perlbreq.src and
doc/pptok.src to have already been generated -- the Unix "doc" target
does this via the top-level Makefile.in before recursing into doc/,
but msvc.mak's docs: target had no equivalent step. warnings.src and
pptok.src already had msvc.mak rules (just not wired up as
prerequisites of docs:); perlbreq.src had no rule at all, since the
top-level Makefile.in generates it with a POSIX find/sed pipeline that
doesn't translate to Windows. Add tools/genperlbreq.pl, a portable
pure-Perl equivalent (using File::Find), and a doc\perlbreq.src rule
in msvc.mak that uses it; verified it produces output byte-identical
to the existing POSIX pipeline.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Note that building the documentation via the "docs" nmake target
requires Ghostscript and the Roboto/Roboto Mono fonts, per
doc/source.src. This target previously also had to work around
doc/Makefile.in containing a bare, unexpanded "@SET_MAKE@" line
(fixed in the preceding commit), which made it a hard nmake parse
error; that workaround is no longer needed.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@SET_MAKE@ (AC_PROG_MAKE_SET) is a legacy autoconf substitution needed
only for very old Unix make implementations that don't automatically
propagate $(MAKE) to recursively invoked sub-makes. Every Makefile.in
in the tree carried its own copy, but that's unnecessary: exporting
MAKE once, from the top-level Makefile.in, is sufficient for it to
reach any sub-make invoked (directly or transitively) from there.
Replace the top-level @SET_MAKE@ with the pair "@SET_MAKE@" followed
by "export MAKE", and drop the now-redundant @SET_MAKE@ line from
doc/Makefile.in, misc/Makefile.in and test/Makefile.in.
This incidentally fixes doc/Makefile.in being usable when fed directly
to nmake (as Mkfiles/msvc.mak's "docs" rule does, since it predates
running ./configure): a bare "@SET_MAKE@" line, left unexpanded, is
not a valid nmake assignment or rule and previously caused a hard
parse error (U1035, "expected ':' or '=' separator").
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Install NSIS via choco (not preinstalled on windows-latest), Ghostscript
via choco, and the Roboto/Roboto Mono fonts (matching the exact
versions Fedora's google-roboto-fonts and google-roboto-mono-fonts
packages ship, dropped straight into %windir%\Fonts, which
doc/findfont.ph's directory-scan fallback picks up without needing
font registration). Then run 'nmake docs' (builds nasmdoc.pdf via
NASM's own Perl-based doc toolchain, which needs exactly those tools --
see doc/source.src) followed by 'nmake nsis' to produce the installer
via nsis/nasm.nsi, and upload it as a workflow artifact.
Ghostscript is located by doc/pspdf.pl via the Windows registry keys
the official installer creates, not via PATH, so no PATH setup is
needed for it.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a build-msvc job on windows-latest that uses
step-security/msvc-dev-cmd to set up the MSVC developer environment,
builds NASM with 'nmake /f Mkfiles/msvc.mak', and smoke-tests the
resulting nasm.exe/ndisasm.exe by assembling and disassembling a tiny
program and building a win64 object file.
step-security/msvc-dev-cmd is a StepSecurity-maintained, drop-in
replacement for the more widely known ilammy/msvc-dev-cmd@v1 action;
the latter's newest release (v1.13.0, Jan 2024) still targets the
now-deprecated Node.js 20 runtime with no newer release in sight,
while step-security's fork tracks Node.js 24.
This is the first CI coverage of the MSVC build path (Mkfiles/msvc.mak
+ config/msvc.h), which previously had no automated verification.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
nasmlib/file.c included <stringapiset.h> directly (for
MultiByteToWideChar()/CompareStringOrdinal()) without first including
<windows.h>. Windows SDK headers like <stringapiset.h> are only
guaranteed to work when pulled in through the normal <windows.h>
pipeline, which sets up SDK-internal architecture macros (_X86_,
_AMD64_, ...) derived from the compiler's own _M_IX86/_M_X64/etc.
Including them directly skips that setup and can fail with a
'No Target Architecture' #error from <winnt.h> -- which is exactly
what happened building with a real cl.exe/nmake in CI.
<windows.h> is deliberately *not* pulled in globally from compiler.h:
it #defines NEAR and FAR as legacy no-op calling-convention keywords,
which clash with NASM's own NEAR/FAR opflags bits (include/opflags.h).
Keep the inclusion local to file.c, the only file that currently needs
Windows API declarations, guarded by WIN32_LEAN_AND_MEAN to keep the
exposed surface minimal.
Confirmed fixed with a real MSVC (cl.exe/nmake) build in CI.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Cross-referenced configure.ac's AC_CHECK_HEADERS/AC_CHECK_FUNCS/PA_*
tests (as materialized into config/config.h.in) against config/msvc.h
and added definitions for macros MSVC actually supports:
- HAVE_STDARG_H, HAVE_STDIO_H, HAVE_WCHAR_H: always present.
- HAVE_STDINT_H: available starting with Visual Studio 2010
(_MSC_VER >= 1600).
- HAVE_INTRIN_H plus an #include <intrin.h>, gated on Visual Studio
2005 (_MSC_VER >= 1400) when the header was introduced.
- HAVE_ISCNTRL: always present.
- HAVE_ISASCII plus '#define isascii __isascii', since MSVC only
provides the underscore-prefixed spelling.
- HAVE__BYTESWAP_USHORT/_ULONG/_UINT64: always present, declared in
<stdlib.h>, matching the names PA_FIND_FUNC probes for in
autoconf/m4/pa_endian.m4.
- HAVE__BITSCANREVERSE (>=1400) and HAVE__BITSCANREVERSE64 (>=1400 and
only on _M_X64/_M_ARM64, since the 64-bit intrinsic does not exist
on 32-bit x86).
- HAVE_UNSIGNED_LONG_LONG_INT: always present.
- HAVE_UINTMAX_T, gated on '#ifdef HAVE_STDINT_H' rather than a
separate version check, with a textual 'unsigned long long'
fallback for uintmax_t otherwise; gating strictly on HAVE_STDINT_H
avoids the fallback macro clobbering <stdint.h>'s own uintmax_t
typedef when both would otherwise be available.
Deliberately left out anything that is POSIX/GNU/BSD-only or does not
exist verbatim on MSVC (strcasecmp/strsep/strlcpy/mempcpy, getuid/
getrlimit/realpath, GCC __builtin_*/attribute probes, byteswap.h/
endian.h family, C23 stdbit.h, etc.), since compiler.h and the
relevant call sites already handle those cases separately for MSVC.
Verified with x86_64-w64-mingw32-gcc -fsyntax-only using manually
defined _MSC_VER/_M_X64/_M_ARM64 across Visual Studio versions
1310/1400/1600/1800/1929 (mingw-w64 declares the same intrinsics in
the expected headers), then confirmed end-to-end with a real MSVC
(cl.exe/nmake) build in CI.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Formalize the mechanism for storing mapped (non-filesystem) filenames
in the filenames array. These are not compared against input or output
files for overwrite checks.
Add the infrastructure for comparing more than one input filename
(future proofing.)
Move the Makefile dependency target name to the filenames system.
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Instead of doing a simple string comparison, call nasm_compare_paths()
to compare infile and outfile paths.
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Add nasm_compare_paths(). At this point, the only effect is wide
character/case insensitivity canonicalization on Windows, but in the
future it might be doing things like comparing st_dev:st_inode pairs
on Unix or compare nasm_realpath().
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Rename travis.mk to .mak to match the convention for all other
Makefiles in the tree (that aren't simply named "Makefile".)
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Remove the long-since-unmaintained test/performtest.pl script and
redirect the "test" and "golden" Makefile targets to their respective
travis targets.
The test/ directory still has two important functions:
1. Running ad hoc tests manually. The test/ directory has
infrastructure for running a quick test manually in a large number
of configurations. This is highly useful during development.
2. It contains the infrastructure for running regression tests on
external applications, far too big to include into NASM itself.
Reported-by: Ross Burton <ross@burtonini.com>
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Instead of generating one single huge line of text, add newlines after
suitable commas to make it at least a manageable text file.
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Adds an option to remap file prefixes in output object files. This is
analogous to the "-fdebug-prefix-map" option in GCC, and allows files to
be built in a reproducible manner regardless of the build directory.
[ hpa: this still needs to be documented in doc/running.src. ]
Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
The cv8struc test ends up with embedded absolute pathnames. This is a
known problem with the reproducibility of this test (see
https://github.com/netwide-assembler/nasm/pull/8) and so disable it
for now, as it generates false positive failures.
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
It is more or less impossible to debug CI/CD test failures without
this file, so make github keep a copy of it.
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
The test.yml file uses actions/checkout@v4, which apparently is being
deprecated; bump to @v6 (using Node.js 24) instead.
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Adds a "Error-case (%ifdef ERROR) coverage" section describing the
needs64/avoid64 dual-source design and the nasm-t.py json convention
reused from travis/ret/ret.json, notes on the two branch-operand bugs
discovered and fixed along the way, and updates the "Known
limitations" and "Validation" sections with the final 2612/10
mnemonic counts and 1976/2612 error-coverage numbers.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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>
For instruction operand tokens that carry an explicit size in their own
name (mem8/16/32/64/..., rm8/16/32/64, xmmrm.../ymmrm256/zmmrm512,
mmxrm/mmxrm64), the generator previously always emitted an explicit size
keyword (e.g. "dword", "oword") for the memory operand. This never
exercised NASM's SM-flag-driven implicit-size-inference path, where the
size of an ambiguous memory operand is inferred from a paired
already-sized operand (typically a same-width register) in the same
instruction template (e.g. ADD reg32,rm32 or MOVBE reg32,mem32 don't
need an explicit size keyword).
Add build_implicitsize_line(), which replaces the first memory-capable
operand whose base token has a nonzero %mem_sizebits entry with a bare
(size-keyword-free) memory operand, leaving all other operands as
normally generated. As with the other coverage buckets (hireg, apxreg,
mask/maskz/broadcast/saeer, disp8/32 boundary), the candidate line is
routed through the shared cumulative staged probe and only kept if it
actually assembles for that instruction -- this avoids needing to parse
and replicate NASM's own SM/AR flag-driven operand-size-disambiguation
logic.
Note: for tokens with no size in their own name (plain "mem"), the
existing mem_operand($rng, 0) generator path already omits the size
keyword unconditionally, so that half of implicit-size coverage was
already exercised prior to this change; only explicitly-sized tokens
needed the new candidate.
Verified via full scratch regeneration (2606 mnemonics / 16 dropped,
unchanged) + nasm-t.py run (6955/6955 PASS, 0 FAIL) + per-mnemonic
.json entry-count diff against the prior committed tree (zero
differences, confirming no bit-width regressions). 1922/2606
mnemonics gained new implicit-size coverage lines. Regenerated
travis/insns/ and validated via 'make -j32 travis' (all PASS, ~26s).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Extend gen-insn-tests.pl to synthesize, for every distinct template
across a mnemonic's entire template set that has a modrm-memory-
capable operand (mem*, rm*, xmmrm*/ymmrm256/zmmrm512, mmxrm*), two
additional candidate lines using [eax+1] and [eax+64] addressing in
place of that operand's usual bare-displacement or register form.
Whether an instruction has a disp8-encodable form (or, for EVEX, what
its compressed-displacement scale factor is) is instruction-specific,
so rather than computing the exact boundary per instruction these two
fixed offsets are used as a baseline: +1 is unambiguously disp8-
encodable everywhere, and +64 lands past the disp8 boundary for
byte-granular encodings while still being a clean multiple of the
larger EVEX compressed-displacement scales.
[eax+N] (rather than a bare displacement, or a bit-width-specific base
register) is used because it's valid addressing syntax at every
--bits width via the 0x67 address-size prefix, confirmed empirically.
Candidates are routed through the same staged, cumulative probe as the
hireg/apxreg/EVEX-decorator buckets, so one bad candidate (e.g. an
instruction with memory-operand restrictions this generator doesn't
model) can't cost a mnemonic its pre-existing coverage.
Regenerated travis/insns/ (2606 mnemonics, 16 dropped, unchanged from
before; 1987 mnemonics gained at least one disp-boundary line).
Validated: nasm-t.py run against a scratch regeneration is 6955/6955
PASS/0 FAIL with per-mnemonic bit-width success counts identical to
the previous committed baseline, and make -j32 travis passes in ~26s.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Extend gen-insn-tests.pl to recognize the four independent EVEX
decorator families encoded in insns.xda operand tokens (|mask, |z,
|b16|b32|b64, |sae|er) and synthesize additional candidate lines
exercising each:
- mask: {k1}-{k7} appended to the marked register/memory operand
- maskz: mask + trailing {z} (zeroing), only where |z co-occurs
- broadcast: {1toN} on a memory operand, N derived from the token's
vector width (xmm/ymm/zmm or explicit mem/rm size) and
the b16/b32/b64 element-width marker
- sae/er: a separate trailing {sae} or {rn|rd|ru|rz-sae} pseudo-
operand, only legal when the marked operand resolves to
a register sized per the token's own declared width
(e.g. rm64|er needs a 64-bit register, not rm32)
Candidate lines are generated once per *distinct* template across each
mnemonic's entire template set, not just the capped per-mnemonic
sample -- EVEX/AVX512 forms are frequently appended well after a
mnemonic's plain SSE/AVX forms in insns.xda (e.g. VMOVAPD's mask-on-
memory-destination forms), so relying on the sample alone would
silently skip them for many mnemonics.
Generalized the item-2 hireg/apxreg staged-fallback probe into a
per-category, cumulative probing loop over all six extra-line buckets
(hireg, apxreg, mask, maskz, broadcast, saeer): each candidate bucket
is tentatively merged into the accepted line set and kept only if the
result still assembles, avoiding the combinatorial blowup of trying
every subset as the number of independent categories grows.
Regenerated travis/insns/ (2606 mnemonics, 16 dropped, unchanged from
before). Validated: nasm-t.py run against a scratch regeneration is
6955/6955 PASS/0 FAIL (identical per-mnemonic bit-width success counts
to the committed baseline), and make -j32 travis passes in ~26s.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add register-number-focused coverage for every operand-class token that
has a hireg (r8-r15 / xmm-zmm8-15) or apxreg (r16-r31 / xmm-zmm16-31)
tier: registers 8+ only exist in 64-bit mode (they need a REX prefix,
or REX2/EVEX register-extension bits for 16-31), so this coverage is
64-bit-only regardless of the base token's own size.
Per template with at least one such token, generate one extra all-hireg
and one extra all-apxreg instruction line (once per template, not once
per --variants instance). Since NASM's own template-matching engine
transparently selects an alternate (e.g. APX/EVEX-encoded) pattern when
the operand syntax calls for it, the generator doesn't need to special-
case APX/EVEX iflags to decide whether extended registers are legal for
a given mnemonic -- it can simply try assembling and keep whichever
combination works. A staged-fallback probe (try hireg+apxreg, then
hireg alone, then apxreg alone, then neither) avoids letting one
genuinely-incompatible extra line (e.g. NOAPX/NOLONG-only mnemonics)
cost the whole mnemonic its pre-existing 64-bit coverage; the probe
checks --bits 16/32 too whenever a mnemonic's *only* templates need
64-bit registers regardless of number (e.g. URDMSR/UWRMSR), since in
that case the generated 'full' file is reused for every bit width.
Also fixes a latent bug: xmmreg/ymmreg/zmmreg previously drew uniformly
from registers 0-15, but 8-15 needs 64-bit mode just like the GPR
case -- so a template could non-deterministically lose its 16/32-bit
coverage whenever the RNG happened to land on 8-15 (e.g. ADDPD was
missing bin16/bin32 goldens before this fix). Register pools are now
split into explicit low (0-7)/hireg (8-15)/apxreg (16-31) tiers per
register class, threaded through gen_operand() via a new
parameter (defaulting to the existing 'low' behavior at all pre-
existing call sites).
Regenerated travis/insns/ (2606 mnemonics, 16 dropped -- unchanged
counts). Full suite validated via make -j32 travis: all tests PASS in
~27s.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
x86/insns.xda marks operands with a trailing '*' (optional source,
duplicates the previous operand in the encoding when omitted --
insns.pl's relaxed_forms() implements the actual encoding semantics for
the C generators) or '?' (optional destination, entirely absent from
the encoding when omitted, e.g. APX NDD forms). Previously the
generator always emitted every operand in a template, so the
omitted-operand parsing/encoding path was never exercised, and
reg8?/reg16?/reg32?-marked templates fell back to the generic '?'-
unaware base_token() lookup and were silently dropped as unsupported
(only the reg64? case happened to have an explicit, redundant table
entry).
base_token() now strips a trailing '?' the same way it already stripped
'*', so all four reg#? variants resolve to their plain register
generator (the redundant explicit reg8?/16?/32?/64? %gen entries are
removed as now-dead code). A new optional_operand_index() locates the
(at most one, per insns.xda) marked operand in a template, and the
per-mnemonic driver emits one additional reduced-arity instruction line
per template (dropping that operand) alongside the existing full-arity
line, so both forms get captured as goldens.
Regenerated travis/insns/ (2606 mnemonics, 16 dropped -- unchanged counts,
since this only adds coverage lines to existing mnemonic asm files, not
new mnemonics). Full suite validated via make -j32 travis: all tests
PASS in ~26s.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Extract the condition-code suffix table (%conds, @conds, and the
c_ccmask/c_nd/c_cc/c_scc bitmasks) out of x86/insns.pl's
conditional_forms() into a new shared x86/insns-cc.ph module, adding
cc_suffix_list($is_scc) to return the suffix list applicable to a
'...cc'-family (Jcc, SETcc, CMOVcc, CFCMOVcc) or '...scc'-family
(CCMPscc, CTESTscc, CMPccXADD, SETccZU) placeholder mnemonic. insns.pl
is refactored to use it (behavior-preserving: verified byte-identical
x86/insnsa.c, insnsb.c, insnsd.c, insnsi.h, insnsn.c, iflag.c,
iflaggen.h, asm/tokhash.c, asm/tokens.h before/after).
tools/testgen/gen-insn-tests.pl now requires the same module instead
of hand-rolling a 16-suffix 'cc'-only expansion table, closing the gap
where the APX 'scc'-suffix families (CCMPscc/CTESTscc/CMPccXADD/
SETccZU) were dropped as unsupported. The generator now detects and
expands any '...cc'/'...scc' placeholder mnemonic the same way
insns.pl's conditional_forms() does (case-sensitive /s?cc/ match and
substitution), so future new cc/scc families need no generator
changes. Mnemonics with generated tests: 2432 -> 2606 (+174, one per
newly-expanded scc-family condition); dropped: 20 -> 16.
Regenerated travis/insns/ (174 new mnemonic dirs for the APX scc
families; existing 2432 regenerated byte-identically, confirming
determinism). Full suite validated both via
tools/travis/nasm-t.py --directory=./travis run (4427 total, 4426
PASS, 1 pre-existing SKIP, 0 FAIL) and via make -j32 travis (all
tests PASS, ~28s).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add gen-insn-tests.pl, a prototype tool that generates one travis test
directory per non-pseudo instruction mnemonic (asm + json + golden
output), by parsing x86/insns.xda (the already-generated, macro-
expanded, one-template-per-line intermediate NASM produces from
insns.dat) rather than insnsa.c/insnsb.c or hooking insns.pl.
Rationale: insnsa.c/insnsb.c encode operands as opaque bitmask
constants and index into an explicitly-unstable, shared bytecode array
(x86/bytecode.txt: byte codes can be moved and recycled at any time),
making them fragile/high-effort to parse from outside insns.pl.
insns.xda already provides exactly the needed semantic info (mnemonic,
comma-separated operand-type tokens, flags) in a small stable text
grammar, with zero changes to insns.pl or the build. We only need
valid operand *syntax* per operand-type token -- NASM picks the
encoding itself from mnemonic + operand syntax -- so the generated
tests are regression tests against a golden captured from a known-good
nasm build, consistent with the rest of travis/.
Includes UNDOC/OBSOLETE/NEVER-flagged instructions (only PSEUDO
pseudo-ops are excluded): where these emit an expected warning (e.g.
-w+obsolete-removed), the generator declares a stderr target so the
warning text itself becomes part of the golden, verifying the warning
fires rather than skipping the coverage.
Delegates golden capture to tools/travis/nasm-t.py update instead of
re-implementing it, so goldens get the harness's existing correctness
properties (reproducible-build NASMENV, path-embedding conventions,
etc.) for free.
Generated travis/insns/<mnemonic>/ for all 2432 assemblable mnemonics
(16/32/64-bit variants as applicable). Full suite validated via
tools/travis/nasm-t.py: 4225 total, 4224 PASS, 1 pre-existing SKIP,
0 FAIL.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The travis tool itself runs all tests it is given in series. Use make
to parallelize running the tests, leaving a log in each subdirectory
in addition to the global log.
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This is a mostly automated, partially AI-assisted migration of tests
from the test/ directory into the travis framework.
Running tests manually in the test/ directory is still supported, but
move common include files into travis/test and add a default -I option
to Makefile.in in the test/ directory.
The incbin test fails for pre-existing reasons; for now it contains an
stderr file with the errors. The problem is that INCBIN is both a
macro and a special instruction (not even a directive...), but there
currently is no way to handle prefixes, *especially* TIMES, in
multi-line macros. This is a separate problem and needs to be dealt
with as such.
Reorganize the travis directory so that each test or collection of
tests are in a separate subdirectory of travis/, and travis itself
lives in tools/travis to avoid creating deeper paths.
Add support for recording compression options in the travis .json
files, so that compressed files can be recreated with the same
options: because of the generally repetitive nature of the binary
output test files, the parameters used for xz compression can matter
enormously.
These are combined into a single huge commit to avoid adding large
binary files into the repository that then would immediately be
obsoleted, but still retained in git.
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Some tests may by necessity generate very large output files. Allow
.xz compression of the reference files to avoid bloating the git
repository too much. The committer of very large files will need to
carefully consider the xz options used to maximize compressibility
especially of highly regular files.
This commit was AI-assisted (Copilot/Claude Sonnet 5).
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
The TMMULTF32PS instruction will not be implemented, mark it as NEVER.
Reported-by: Christian Ludloff <ludloff@github.com>
Fixes: https://github.com/netwide-assembler/nasm/issues/259
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
The number of entries in a group was hard-coded, but not enforced.
Reported-by: <BreakingBad6@github.com>
Fixes: https://github.com/netwide-assembler/nasm/issues/203
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
- Register the map file with the filename system.
- Check to see if the mapfile is clobbering the input.
- Remove the map file if the output file is also removed.
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Replace the direct setting of variables for input and output variables
with accessors. This allows for properly tracking the lifetimes of the
data and allows for things like checking of the overwrite of the
primary input file to be centralized.
It isn't possible *in the general case* to check for overwrite of
*any* of the input files, although in the particularly important case
of the assembler proper it ought to be possible to do a bit better:
it should be able to guard for overwrites of non-primary input files
except for the error file or the list file if and only if -Lp is used.
That is, however, a latter project.
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Add nasm_remove() to mangle a filename if necessary before calling
an OS-specific remove() function. This allows calling _wremove() on
Windows.
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
The example used %define but it really needs to use %xdefine in order
to snapshot the value of __?LIST_OPTIONS?__.
Tidy it up a little as well.
Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>