aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2020-07-05 16:27:38 -0700
committerH. Peter Anvin <hpa@zytor.com>2020-07-05 16:27:38 -0700
commit9d50a184a1c0bb05bcb210c1f676b6ac1bbb174b (patch)
treedf2da4cc1684c8b8e939366422b86dace1d0ea8f
parentc5717a8204b5fcd383cf9e0a237c4727feccb5bd (diff)
parentf293842b8a5e85506d0e67e20cbe5b62b60e6e61 (diff)
downloadnasm-loops.tar.gz
nasm-loops.tar.xz
nasm-loops.zip
Merge remote-tracking branch 'github/master' into loopsloops
This merge contains fixes of bugs uncovered during conflict resolution. After this merge, "make travis" passes! Signed-off-by: H. Peter Anvin <hpa@zytor.com> Resolved Conflicts:
-rw-r--r--.gitattributes1
-rw-r--r--.gitignore1
-rw-r--r--Makefile.in75
-rw-r--r--Mkfiles/msvc.mak12
-rw-r--r--Mkfiles/openwcom.mak10
-rw-r--r--README.md2
-rw-r--r--asm/assemble.c291
-rw-r--r--asm/directiv.c2
-rw-r--r--asm/error.c8
-rw-r--r--asm/eval.c2
-rw-r--r--asm/floats.c (renamed from asm/float.c)2
-rw-r--r--asm/floats.h (renamed from asm/float.h)10
-rw-r--r--asm/listing.c66
-rw-r--r--asm/nasm.c374
-rw-r--r--asm/parser.c450
-rw-r--r--asm/pptok.dat2
-rwxr-xr-xasm/pptok.pl6
-rw-r--r--asm/preproc.c1400
-rw-r--r--asm/srcfile.c41
-rw-r--r--asm/srcfile.h89
-rw-r--r--asm/stdscan.c4
-rw-r--r--asm/tokens.dat6
-rwxr-xr-xasm/tokhash.pl6
-rwxr-xr-xasm/warnings.pl13
-rw-r--r--config/unconfig.h36
-rw-r--r--configure.ac96
-rw-r--r--disasm/ndisasm.c4
-rw-r--r--doc/Makefile.in49
-rw-r--r--doc/changes.src117
-rwxr-xr-xdoc/genps.pl8
-rw-r--r--doc/head.ps8
-rw-r--r--doc/nasmdoc.css1
-rw-r--r--doc/nasmdoc.src859
-rw-r--r--doc/psfonts.ph47
-rwxr-xr-xdoc/pspdf.pl8
-rw-r--r--include/compiler.h12
-rw-r--r--include/error.h20
-rw-r--r--include/nasm.h58
-rw-r--r--include/nasmlib.h13
-rw-r--r--include/rbtree.h49
-rw-r--r--include/strlist.h10
-rwxr-xr-xmacros/macros.pl6
-rw-r--r--nasm.spec.in4
-rw-r--r--nasmlib/file.c19
-rw-r--r--nasmlib/file.h22
-rw-r--r--nasmlib/hashtbl.c5
-rwxr-xr-xnasmlib/perfhash.pl6
-rw-r--r--nasmlib/rbtree.c212
-rw-r--r--nasmlib/rlimit.c78
-rw-r--r--nasmlib/strlist.c5
-rw-r--r--output/codeview.c62
-rw-r--r--output/outelf.c182
-rw-r--r--output/outlib.c278
-rw-r--r--output/outlib.h252
-rw-r--r--output/outobj.c6
-rw-r--r--test/Makefile19
-rw-r--r--test/a64.asm22
-rw-r--r--test/binoverflow.asm37
-rw-r--r--test/br3392607.asm2
-rw-r--r--test/br3392626.asm6
-rw-r--r--test/br3392640.asm4
-rw-r--r--test/br3392660.asm9
-rw-r--r--test/br3392661.asm8
-rw-r--r--test/br3392667.asmbin0 -> 29768 bytes
-rw-r--r--test/br3392668-3.asmbin0 -> 130926 bytes
-rw-r--r--test/br3392669-57.asmbin0 -> 2790 bytes
-rw-r--r--test/defalias.asm52
-rw-r--r--test/dup.asm36
-rw-r--r--test/emptyarg.asm147
-rw-r--r--test/exitrep.asm30
-rw-r--r--test/ifdef.asm7
-rw-r--r--test/include-self.asm2
-rw-r--r--test/require.asm2
-rw-r--r--test/xdefine.asm15
-rw-r--r--test/xpaste.asm6
-rwxr-xr-xtools/mkdep.pl21
-rwxr-xr-xtools/release5
-rw-r--r--travis/test/_version.stdout2
-rw-r--r--travis/test/avx512f.bin.tbin0 -> 56620 bytes
-rw-r--r--travis/test/avx512f.json3
-rw-r--r--travis/test/avx512f.stderr572
-rw-r--r--travis/test/utf-error.stderr3
-rw-r--r--travis/test/weirdpaste.i.t19
-rw-r--r--version2
-rw-r--r--x86/iflags.ph1
-rw-r--r--x86/insns.dat684
86 files changed, 5028 insertions, 2093 deletions
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..d94c5fb3
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+/version -merge
diff --git a/.gitignore b/.gitignore
index 63b3470a..b22d2ab8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,6 +59,7 @@ TAGS
/doc/*.dip
/doc/*.hpj
/doc/*.pdf
+/doc/*.pdf.xz
/doc/*.ps
/doc/*.rtf
/doc/*.texi
diff --git a/Makefile.in b/Makefile.in
index 68ec9d45..8c8e1d54 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -47,13 +47,18 @@ INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
+# Optional tools
NROFF = @NROFF@
ASCIIDOC = @ASCIIDOC@
XMLTO = @XMLTO@
+MAKENSIS = @MAKENSIS@
+XZ = @XZ@
-MAKENSIS = makensis
+# Optional targets
+MANPAGES = @MANPAGES@
+NSIS = @NSIS@
-MKDIR = mkdir -p
+MKDIR_P = @MKDIR_P@
RM_F = rm -f
RM_RF = rm -rf
LN_S = @LN_S@
@@ -74,7 +79,7 @@ endif
.PHONY: all doc rdf install clean distclean cleaner spotless install_rdf test
.PHONY: install_doc everything install_everything strip perlreq dist tags TAGS
-.PHONY: manpages nsis
+.PHONY: nothing manpages nsis
.c.$(O):
$(CC) -c $(ALL_CFLAGS) -o $@ $<
@@ -104,7 +109,7 @@ LIBOBJ = stdlib/snprintf.$(O) stdlib/vsnprintf.$(O) stdlib/strlcpy.$(O) \
nasmlib/string.$(O) nasmlib/nctype.$(O) \
nasmlib/file.$(O) nasmlib/mmap.$(O) nasmlib/ilog2.$(O) \
nasmlib/realpath.$(O) nasmlib/path.$(O) \
- nasmlib/filename.$(O) \
+ nasmlib/filename.$(O) nasmlib/rlimit.$(O) \
nasmlib/zerobuf.$(O) nasmlib/readnum.$(O) nasmlib/bsi.$(O) \
nasmlib/rbtree.$(O) nasmlib/hashtbl.$(O) \
nasmlib/raa.$(O) nasmlib/saa.$(O) \
@@ -118,7 +123,7 @@ LIBOBJ = stdlib/snprintf.$(O) stdlib/vsnprintf.$(O) stdlib/strlcpy.$(O) \
x86/disp8.$(O) x86/iflag.$(O) \
\
asm/error.$(O) asm/warnings.$(O) \
- asm/float.$(O) \
+ asm/floats.$(O) \
asm/directiv.$(O) asm/directbl.$(O) \
asm/pragma.$(O) \
asm/assemble.$(O) asm/labels.$(O) asm/parser.$(O) \
@@ -147,10 +152,14 @@ XSUBDIRS = test doc nsis rdoff
DEPDIRS = . include config x86 rdoff $(SUBDIRS)
#-- End File Lists --#
-all: nasm$(X) ndisasm$(X) rdf
+all: dirs
+ $(MAKE) nasm$(X) ndisasm$(X) rdf
NASMLIB = libnasm.$(A)
+dirs:
+ $(MKDIR_P) $(SUBDIRS) $(XSUBDIRS)
+
$(NASMLIB): $(LIBOBJ)
$(RM_F) $(NASMLIB)
$(AR) cq $(NASMLIB) $(LIBOBJ)
@@ -175,7 +184,7 @@ PERLREQ = x86/insnsb.c x86/insnsa.c x86/insnsd.c x86/insnsi.h x86/insnsn.c \
x86/iflag.c x86/iflaggen.h \
macros/macros.c \
asm/pptok.ph asm/directbl.c asm/directiv.h \
- asm/warnings.c include/warnings.h \
+ asm/warnings.c include/warnings.h doc/warnings.src \
version.h version.mac version.mak nsis/version.nsh
INSDEP = x86/insns.dat x86/insns.pl x86/insns-iflags.ph x86/iflags.ph
@@ -249,7 +258,7 @@ x86/regs.h: x86/regs.dat x86/regs.pl
WARNFILES = asm/warnings.c include/warnings.h doc/warnings.src
warnings:
- rm -f $(WARNFILES)
+ $(RM_F) $(WARNFILES)
$(MAKE) $(WARNFILES)
asm/warnings.c: asm/warnings.pl
@@ -348,8 +357,6 @@ $(RDFLIB): $(RDFLIBOBJ)
#-- Begin NSIS Rules --#
-# NSIS is not built except by explicit request, as it only applies to
-# Windows platforms
nsis/arch.nsh: nsis/getpearch.pl nasm$(X)
$(PERL) $(srcdir)/nsis/getpearch.pl nasm$(X) > nsis/arch.nsh
@@ -365,10 +372,10 @@ nsis: nsis/nasm.nsi nsis/arch.nsh nsis/version.nsh
manpages: nasm.1 ndisasm.1
install: nasm$(X) ndisasm$(X)
- $(MKDIR) $(DESTDIR)$(bindir)
+ $(MKDIR_P) $(DESTDIR)$(bindir)
$(INSTALL_PROGRAM) nasm$(X) $(DESTDIR)$(bindir)/nasm$(X)
$(INSTALL_PROGRAM) ndisasm$(X) $(DESTDIR)$(bindir)/ndisasm$(X)
- $(MKDIR) $(DESTDIR)$(mandir)/man1
+ $(MKDIR_P) $(DESTDIR)$(mandir)/man1
$(INSTALL_DATA) $(srcdir)/nasm.1 $(DESTDIR)$(mandir)/man1/nasm.1
$(INSTALL_DATA) $(srcdir)/ndisasm.1 $(DESTDIR)$(mandir)/man1/ndisasm.1
@@ -386,7 +393,8 @@ clean:
distclean: clean
$(RM_F) config.log config.status config/config.h
for d in . $(SUBDIRS) $(XSUBDIRS); do \
- $(RM_F) "$$d"/*~ "$$d"/*.bak "$$d"/*.lst "$$d"/*.bin ; \
+ $(RM_F) "$$d"/.\# "$$d"/\# "$$d"/*~ "$$d"/*.bak \
+ "$$d"/*.lst "$$d"/*.bin ; \
done
$(RM_F) test/*.$(O)
$(RM_RF) autom4te*.cache
@@ -417,7 +425,7 @@ cscope:
cscope -b -f cscope.out
rdf_install install_rdf install_rdoff:
- $(MKDIR) $(DESTDIR)$(bindir)
+ $(MKDIR_P) $(DESTDIR)$(bindir)
for f in $(RDFPROGS); do \
$(INSTALL_PROGRAM) "$$f" '$(DESTDIR)$(bindir)'/ ; \
done
@@ -426,7 +434,7 @@ rdf_install install_rdf install_rdoff:
bn=`basename "$$f"` && $(RM_F) "$$bn" && \
$(LN_S) rdf2bin$(X) "$$bn" ; \
done
- $(MKDIR) $(DESTDIR)$(mandir)/man1
+ $(MKDIR_P) $(DESTDIR)$(mandir)/man1
$(INSTALL_DATA) $(srcdir)/rdoff/*.1 $(DESTDIR)$(mandir)/man1/
doc: doc/warnings.src
@@ -435,19 +443,28 @@ doc: doc/warnings.src
doc_install install_doc:
$(MAKE) -C doc install
-everything: all manpages doc rdf
+# Dummy target to prevent accidental invocation of the default "all" target
+nothing:
+
+always_everything: dirs
+ $(MAKE) all doc
+
+everything: always_everything
+ $(MAKE) $(MANPAGES) $(NSIS) nothing
install_everything: everything install install_doc install_rdf
dist:
$(MAKE) alldeps
- $(MAKE) spotless perlreq manpages spec
+ $(MAKE) spotless perlreq manpages spec $(MANPAGES)
autoheader
autoconf
$(RM_RF) ./autom4te*.cache
tar: dist
- tar -cvj --exclude CVS -C .. -f ../nasm-`cat version`-`date +%Y%m%d`.tar.bz2 `basename \`pwd\``
+ tar -cv --exclude CVS -C .. -f - | \
+ $(XZ) -9e > \
+ ../nasm-`cat version`-`date +%Y%m%d`.tar.xz `basename \`pwd\``
spec: nasm.spec
@@ -456,11 +473,11 @@ ALLPERLSRC := $(shell find $(srcdir) -type f -name '*.p[lh]')
perlbreq.si: $(ALLPERLSRC)
sed -n -r -e 's/^[[:space:]]*use[[:space:]]+([^[:space:];]+).*$$/BuildRequires: perl(\1)/p' $(ALLPERLSRC) | \
sed -r -e '/perl\((strict|warnings|Win32.*)\)/d' | \
- sort | uniq > perlbreq.si || ( rm -f perlbreq.si ; false )
+ sort | uniq > perlbreq.si
nasm.spec: nasm.spec.in nasm.spec.sed version.sed perlbreq.si
sed -f version.sed -f nasm.spec.sed \
- < nasm.spec.in > nasm.spec || ( rm -f nasm.spec ; false )
+ < nasm.spec.in > nasm.spec
splint:
splint -weak *.c
@@ -495,6 +512,14 @@ doc/Makefile: Makefile
config/config.h: config.status
#
+# Dummy rules that changes make behavior
+# (at end to avoid confusing non-GNU makes)
+#
+.SECONDARY:
+
+.DELETE_ON_ERROR:
+
+#
# Does this version of this file have external dependencies? This definition
# will be automatically updated by mkdep.pl as needed.
#
@@ -523,9 +548,6 @@ alldeps: $(PERLREQ) tools/syncfiles.pl tools/mkdep.pl
$(DEPDIRS)
$(RM_F) *.dep
if [ -f config.status ]; then \
- if [ $(EXTERNAL_DEPENDENCIES) -eq 1 ]; then \
- sh config.status --recheck; \
- fi; \
sh config.status; \
fi
@@ -537,9 +559,6 @@ cleandeps: $(PERLREQ) tools/syncfiles.pl tools/mkdep.pl
$(DEPDIRS)
$(RM_F) *.dep
if [ -f config.status ]; then \
- if [ $(EXTERNAL_DEPENDENCIES) -eq 0 ]; then \
- sh config.status --recheck; \
- fi; \
sh config.status; \
fi
@@ -547,7 +566,7 @@ cleandeps: $(PERLREQ) tools/syncfiles.pl tools/mkdep.pl
# @object-ending: ".$(O)"
# @path-separator: "/"
# @external: "Makefile.dep"
-# @include-command: "-include"
+# @include-command: "include"
# @selfrule: "1"
#-- Everything below is generated by mkdep.pl - do not edit --#
--include Makefile.dep
+include Makefile.dep
diff --git a/Mkfiles/msvc.mak b/Mkfiles/msvc.mak
index 25667a37..a22b2cbe 100644
--- a/Mkfiles/msvc.mak
+++ b/Mkfiles/msvc.mak
@@ -73,7 +73,7 @@ LIBOBJ = stdlib\snprintf.$(O) stdlib\vsnprintf.$(O) stdlib\strlcpy.$(O) \
nasmlib\string.$(O) nasmlib\nctype.$(O) \
nasmlib\file.$(O) nasmlib\mmap.$(O) nasmlib\ilog2.$(O) \
nasmlib\realpath.$(O) nasmlib\path.$(O) \
- nasmlib\filename.$(O) \
+ nasmlib\filename.$(O) nasmlib\rlimit.$(O) \
nasmlib\zerobuf.$(O) nasmlib\readnum.$(O) nasmlib\bsi.$(O) \
nasmlib\rbtree.$(O) nasmlib\hashtbl.$(O) \
nasmlib\raa.$(O) nasmlib\saa.$(O) \
@@ -87,7 +87,7 @@ LIBOBJ = stdlib\snprintf.$(O) stdlib\vsnprintf.$(O) stdlib\strlcpy.$(O) \
x86\disp8.$(O) x86\iflag.$(O) \
\
asm\error.$(O) asm\warnings.$(O) \
- asm\float.$(O) \
+ asm\floats.$(O) \
asm\directiv.$(O) asm\directbl.$(O) \
asm\pragma.$(O) \
asm\assemble.$(O) asm\labels.$(O) asm\parser.$(O) \
@@ -143,7 +143,7 @@ PERLREQ = x86\insnsb.c x86\insnsa.c x86\insnsd.c x86\insnsi.h x86\insnsn.c \
x86\iflag.c x86\iflaggen.h \
macros\macros.c \
asm\pptok.ph asm\directbl.c asm\directiv.h \
- asm\warnings.c include\warnings.h \
+ asm\warnings.c include\warnings.h doc\warnings.src \
version.h version.mac version.mak nsis\version.nsh
INSDEP = x86\insns.dat x86\insns.pl x86\insns-iflags.ph x86\iflags.ph
@@ -217,7 +217,7 @@ x86\regs.h: x86\regs.dat x86\regs.pl
WARNFILES = asm\warnings.c include\warnings.h doc\warnings.src
warnings:
- rm -f $(WARNFILES)
+ $(RM_F) $(WARNFILES)
$(MAKE) $(WARNFILES)
asm\warnings.c: asm\warnings.pl
@@ -316,8 +316,6 @@ $(RDFLIB): $(RDFLIBOBJ)
#-- Begin NSIS Rules --#
# Edit in Makefile.in, not here!
-# NSIS is not built except by explicit request, as it only applies to
-# Windows platforms
nsis\arch.nsh: nsis\getpearch.pl nasm$(X)
$(PERL) $(srcdir)\nsis\getpearch.pl nasm$(X) > nsis\arch.nsh
@@ -411,7 +409,7 @@ MKDEP=0
#-- Magic hints to mkdep.pl --#
# @object-ending: ".$(O)"
# @path-separator: "\"
-# @exclude: "config\config.h"
+# @exclude: "config/config.h"
# @external: "msvc.dep"
# @selfrule: "1"
#-- Everything below is generated by mkdep.pl - do not edit --#
diff --git a/Mkfiles/openwcom.mak b/Mkfiles/openwcom.mak
index 1a0c3d10..73e0d1bc 100644
--- a/Mkfiles/openwcom.mak
+++ b/Mkfiles/openwcom.mak
@@ -62,7 +62,7 @@ LIBOBJ = stdlib\snprintf.$(O) stdlib\vsnprintf.$(O) stdlib\strlcpy.$(O) &
nasmlib\string.$(O) nasmlib\nctype.$(O) &
nasmlib\file.$(O) nasmlib\mmap.$(O) nasmlib\ilog2.$(O) &
nasmlib\realpath.$(O) nasmlib\path.$(O) &
- nasmlib\filename.$(O) &
+ nasmlib\filename.$(O) nasmlib\rlimit.$(O) &
nasmlib\zerobuf.$(O) nasmlib\readnum.$(O) nasmlib\bsi.$(O) &
nasmlib\rbtree.$(O) nasmlib\hashtbl.$(O) &
nasmlib\raa.$(O) nasmlib\saa.$(O) &
@@ -76,7 +76,7 @@ LIBOBJ = stdlib\snprintf.$(O) stdlib\vsnprintf.$(O) stdlib\strlcpy.$(O) &
x86\disp8.$(O) x86\iflag.$(O) &
&
asm\error.$(O) asm\warnings.$(O) &
- asm\float.$(O) &
+ asm\floats.$(O) &
asm\directiv.$(O) asm\directbl.$(O) &
asm\pragma.$(O) &
asm\assemble.$(O) asm\labels.$(O) asm\parser.$(O) &
@@ -156,7 +156,7 @@ PERLREQ = x86\insnsb.c x86\insnsa.c x86\insnsd.c x86\insnsi.h x86\insnsn.c &
x86\iflag.c x86\iflaggen.h &
macros\macros.c &
asm\pptok.ph asm\directbl.c asm\directiv.h &
- asm\warnings.c include\warnings.h &
+ asm\warnings.c include\warnings.h doc\warnings.src &
version.h version.mac version.mak nsis\version.nsh
INSDEP = x86\insns.dat x86\insns.pl x86\insns-iflags.ph x86\iflags.ph
@@ -230,7 +230,7 @@ x86\regs.h: x86\regs.dat x86\regs.pl
WARNFILES = asm\warnings.c include\warnings.h doc\warnings.src
warnings:
- rm -f $(WARNFILES)
+ $(RM_F) $(WARNFILES)
$(MAKE) $(WARNFILES)
asm\warnings.c: asm\warnings.pl
@@ -282,8 +282,6 @@ perlreq: $(PERLREQ) .SYMBOLIC
#-- Begin NSIS Rules --#
# Edit in Makefile.in, not here!
-# NSIS is not built except by explicit request, as it only applies to
-# Windows platforms
nsis\arch.nsh: nsis\getpearch.pl nasm$(X)
$(PERL) $(srcdir)\nsis\getpearch.pl nasm$(X) > nsis\arch.nsh
diff --git a/README.md b/README.md
index 704fba14..e9b3dc30 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,5 @@ This means its development is open to even wider society of programmers
wishing to improve their lovely assembler.
Visit our [nasm.us](https://www.nasm.us/) website for more details.
-We are gradually moving services away from Sourceforge. For our remaining
-Sourceforge services see [here](https://sourceforge.net/projects/nasm/).
With best regards, the NASM crew.
diff --git a/asm/assemble.c b/asm/assemble.c
index 875a0d32..e5d5682c 100644
--- a/asm/assemble.c
+++ b/asm/assemble.c
@@ -601,6 +601,83 @@ static inline int64_t merge_resb(insn *ins, int64_t isize)
return isize;
}
+/* This must be handle non-power-of-2 alignment values */
+static inline size_t pad_bytes(size_t len, size_t align)
+{
+ size_t partial = len % align;
+ return partial ? align - partial : 0;
+}
+
+static void out_eops(struct out_data *data, const extop *e)
+{
+ while (e) {
+ size_t dup = e->dup;
+
+ switch (e->type) {
+ case EOT_NOTHING:
+ break;
+
+ case EOT_EXTOP:
+ while (dup--)
+ out_eops(data, e->val.subexpr);
+ break;
+
+ case EOT_DB_NUMBER:
+ if (e->elem > 8) {
+ nasm_nonfatal("integer supplied as %d-bit data",
+ e->elem << 3);
+ } else {
+ while (dup--) {
+ data->insoffs = 0;
+ data->inslen = data->size = e->elem;
+ data->tsegment = e->val.num.segment;
+ data->toffset = e->val.num.offset;
+ data->twrt = e->val.num.wrt;
+ data->relbase = 0;
+ if (e->val.num.segment != NO_SEG &&
+ (e->val.num.segment & 1)) {
+ data->type = OUT_SEGMENT;
+ data->sign = OUT_UNSIGNED;
+ } else {
+ data->type = e->val.num.relative
+ ? OUT_RELADDR : OUT_ADDRESS;
+ data->sign = OUT_WRAP;
+ }
+ out(data);
+ }
+ }
+ break;
+
+ case EOT_DB_FLOAT:
+ case EOT_DB_STRING:
+ case EOT_DB_STRING_FREE:
+ {
+ size_t pad, len;
+
+ pad = pad_bytes(e->val.string.len, e->elem);
+ len = e->val.string.len + pad;
+
+ while (dup--) {
+ data->insoffs = 0;
+ data->inslen = len;
+ out_rawdata(data, e->val.string.data, e->val.string.len);
+ if (pad)
+ out_rawdata(data, zero_buffer, pad);
+ }
+ break;
+ }
+
+ case EOT_DB_RESERVE:
+ data->insoffs = 0;
+ data->inslen = dup * e->elem;
+ out_reserve(data, data->inslen);
+ break;
+ }
+
+ e = e->next;
+ }
+}
+
/* This is totally just a wild guess what is reasonable... */
#define INCBIN_MAX_BUF (ZERO_BUF_SIZE * 16)
@@ -609,7 +686,9 @@ int64_t assemble(int32_t segment, int64_t start, int bits, insn *instruction)
struct out_data data;
const struct itemplate *temp;
enum match_result m;
- int64_t wsize; /* size for DB etc. */
+
+ if (instruction->opcode == I_none)
+ return 0;
nasm_zero(data);
data.offset = start;
@@ -617,49 +696,10 @@ int64_t assemble(int32_t segment, int64_t start, int bits, insn *instruction)
data.itemp = NULL;
data.bits = bits;
- wsize = db_bytes(instruction->opcode);
- if (wsize == -1)
- return 0;
-
- if (wsize) {
- extop *e;
-
- list_for_each(e, instruction->eops) {
- if (e->type == EOT_DB_NUMBER) {
- if (wsize > 8) {
- nasm_nonfatal("integer supplied to a DT,DO,DY or DZ");
- } else {
- data.insoffs = 0;
- data.inslen = data.size = wsize;
- data.toffset = e->offset;
- data.twrt = e->wrt;
- data.relbase = 0;
- if (e->segment != NO_SEG && (e->segment & 1)) {
- data.tsegment = e->segment;
- data.type = OUT_SEGMENT;
- data.sign = OUT_UNSIGNED;
- } else {
- data.tsegment = e->segment;
- data.type = e->relative ? OUT_RELADDR : OUT_ADDRESS;
- data.sign = OUT_WRAP;
- }
- out(&data);
- }
- } else if (e->type == EOT_DB_STRING ||
- e->type == EOT_DB_STRING_FREE) {
- int align = e->stringlen % wsize;
- if (align)
- align = wsize - align;
-
- data.insoffs = 0;
- data.inslen = e->stringlen + align;
-
- out_rawdata(&data, e->stringval, e->stringlen);
- out_rawdata(&data, zero_buffer, align);
- }
- }
+ if (opcode_is_db(instruction->opcode)) {
+ out_eops(&data, instruction->eops);
} else if (instruction->opcode == I_INCBIN) {
- const char *fname = instruction->eops->stringval;
+ const char *fname = instruction->eops->val.string.data;
FILE *fp;
size_t t = instruction->times; /* INCBIN handles TIMES by itself */
off_t base = 0;
@@ -688,14 +728,14 @@ int64_t assemble(int32_t segment, int64_t start, int bits, insn *instruction)
}
if (instruction->eops->next) {
- base = instruction->eops->next->offset;
+ base = instruction->eops->next->val.num.offset;
if (base >= len) {
len = 0;
} else {
len -= base;
if (instruction->eops->next->next &&
- len > (off_t)instruction->eops->next->next->offset)
- len = (off_t)instruction->eops->next->next->offset;
+ len > (off_t)instruction->eops->next->next->val.num.offset)
+ len = (off_t)instruction->eops->next->next->val.num.offset;
}
}
@@ -897,45 +937,57 @@ int64_t assemble(int32_t segment, int64_t start, int bits, insn *instruction)
return data.offset - start;
}
-static void debug_set_db_type(insn *instruction)
+static int32_t eops_typeinfo(const extop *e)
{
- /* Is this really correct? .operands doesn't mean much for Dx */
- int32_t typeinfo = TYS_ELEMENTS(instruction->operands);
+ int32_t typeinfo = 0;
- switch (instruction->opcode) {
- case I_DB:
- typeinfo |= TY_BYTE;
- break;
- case I_DW:
- typeinfo |= TY_WORD;
- break;
- case I_DD:
- if (instruction->eops_float)
- typeinfo |= TY_FLOAT;
- else
- typeinfo |= TY_DWORD;
- break;
- case I_DQ:
- /* What about double? */
- typeinfo |= TY_QWORD;
- break;
- case I_DT:
- /* What about long double? */
- typeinfo |= TY_TBYTE;
- break;
- case I_DO:
- typeinfo |= TY_OWORD;
- break;
- case I_DY:
- typeinfo |= TY_YWORD;
- break;
- case I_DZ:
- typeinfo |= TY_ZWORD;
- break;
- default:
- panic();
+ while (e) {
+ switch (e->type) {
+ case EOT_NOTHING:
+ break;
+
+ case EOT_EXTOP:
+ typeinfo |= eops_typeinfo(e->val.subexpr);
+ break;
+
+ case EOT_DB_FLOAT:
+ switch (e->elem) {
+ case 1: typeinfo |= TY_BYTE; break;
+ case 2: typeinfo |= TY_WORD; break;
+ case 4: typeinfo |= TY_FLOAT; break;
+ case 8: typeinfo |= TY_QWORD; break; /* double? */
+ case 10: typeinfo |= TY_TBYTE; break; /* long double? */
+ case 16: typeinfo |= TY_YWORD; break;
+ case 32: typeinfo |= TY_ZWORD; break;
+ default: break;
+ }
+ break;
+
+ default:
+ switch (e->elem) {
+ case 1: typeinfo |= TY_BYTE; break;
+ case 2: typeinfo |= TY_WORD; break;
+ case 4: typeinfo |= TY_DWORD; break;
+ case 8: typeinfo |= TY_QWORD; break;
+ case 10: typeinfo |= TY_TBYTE; break;
+ case 16: typeinfo |= TY_YWORD; break;
+ case 32: typeinfo |= TY_ZWORD; break;
+ default: break;
+ }
+ break;
+ }
+ e = e->next;
}
+ return typeinfo;
+}
+
+static inline void debug_set_db_type(insn *instruction)
+{
+
+ int32_t typeinfo = TYS_ELEMENTS(instruction->operands);
+
+ typeinfo |= eops_typeinfo(instruction->eops);
dfmt->debug_typevalue(typeinfo);
}
@@ -1009,6 +1061,42 @@ static void define_equ(insn * instruction)
}
}
+static int64_t len_extops(const extop *e)
+{
+ int64_t isize = 0;
+ size_t pad;
+
+ while (e) {
+ switch (e->type) {
+ case EOT_NOTHING:
+ break;
+
+ case EOT_EXTOP:
+ isize += e->dup * len_extops(e->val.subexpr);
+ break;
+
+ case EOT_DB_STRING:
+ case EOT_DB_STRING_FREE:
+ case EOT_DB_FLOAT:
+ pad = pad_bytes(e->val.string.len, e->elem);
+ isize += e->dup * (e->val.string.len + pad);
+ break;
+
+ case EOT_DB_NUMBER:
+ warn_overflow_const(e->val.num.offset, e->elem);
+ isize += e->dup * e->elem;
+ break;
+
+ case EOT_DB_RESERVE:
+ isize += e->dup;
+ break;
+ }
+
+ e = e->next;
+ }
+
+ return isize;
+}
int64_t insn_size(int32_t segment, int64_t offset, int bits, insn *instruction)
{
@@ -1022,33 +1110,12 @@ int64_t insn_size(int32_t segment, int64_t offset, int bits, insn *instruction)
define_equ(instruction);
return 0;
} else if (opcode_is_db(instruction->opcode)) {
- extop *e;
- int32_t osize, wsize;
-
- wsize = db_bytes(instruction->opcode);
- nasm_assert(wsize > 0);
-
- list_for_each(e, instruction->eops) {
- int32_t align;
-
- osize = 0;
- if (e->type == EOT_DB_NUMBER) {
- osize = 1;
- warn_overflow_const(e->offset, wsize);
- } else if (e->type == EOT_DB_STRING ||
- e->type == EOT_DB_STRING_FREE)
- osize = e->stringlen;
-
- align = (-osize) % wsize;
- if (align < 0)
- align += wsize;
- isize += osize + align;
- }
-
+ isize = len_extops(instruction->eops);
debug_set_db_type(instruction);
return isize;
} else if (instruction->opcode == I_INCBIN) {
- const char *fname = instruction->eops->stringval;
+ const extop *e = instruction->eops;
+ const char *fname = e->val.string.data;
off_t len;
len = nasm_file_size_by_path(fname);
@@ -1058,14 +1125,15 @@ int64_t insn_size(int32_t segment, int64_t offset, int bits, insn *instruction)
return 0;
}
- if (instruction->eops->next) {
- if (len <= (off_t)instruction->eops->next->offset) {
+ e = e->next;
+ if (e) {
+ if (len <= (off_t)e->val.num.offset) {
len = 0;
} else {
- len -= instruction->eops->next->offset;
- if (instruction->eops->next->next &&
- len > (off_t)instruction->eops->next->next->offset) {
- len = (off_t)instruction->eops->next->next->offset;
+ len -= e->val.num.offset;
+ e = e->next;
+ if (e && len > (off_t)e->val.num.offset) {
+ len = (off_t)e->val.num.offset;
}
}
}
@@ -2015,7 +2083,6 @@ static void gencode(struct out_data *data, insn *ins)
break;
case 0313:
- ins->rex = 0;
break;
case4(0314):
diff --git a/asm/directiv.c b/asm/directiv.c
index 96464d62..53422098 100644
--- a/asm/directiv.c
+++ b/asm/directiv.c
@@ -43,7 +43,7 @@
#include "nasmlib.h"
#include "ilog2.h"
#include "error.h"
-#include "float.h"
+#include "floats.h"
#include "stdscan.h"
#include "preproc.h"
#include "eval.h"
diff --git a/asm/error.c b/asm/error.c
index ffe7a2e5..1e241c7b 100644
--- a/asm/error.c
+++ b/asm/error.c
@@ -241,8 +241,12 @@ bool set_warning_status(const char *value)
vlen = value ? strlen(value) : 0;
- /* This is inefficient, but it shouldn't matter... */
- for (wa = warning_alias; wa < &warning_alias[NUM_WARNING_ALIAS]; wa++) {
+ /*
+ * This is inefficient, but it shouldn't matter.
+ * Note: warning_alias[0] is "all".
+ */
+ for (wa = warning_alias+1;
+ wa < &warning_alias[NUM_WARNING_ALIAS]; wa++) {
enum warn_index i = wa->warning;
if (value) {
diff --git a/asm/eval.c b/asm/eval.c
index 0dd7e61a..cd3c526d 100644
--- a/asm/eval.c
+++ b/asm/eval.c
@@ -45,7 +45,7 @@
#include "error.h"
#include "eval.h"
#include "labels.h"
-#include "float.h"
+#include "floats.h"
#include "assemble.h"
#define TEMPEXPRS_DELTA 128
diff --git a/asm/float.c b/asm/floats.c
index 77d576c6..adc6afbf 100644
--- a/asm/float.c
+++ b/asm/floats.c
@@ -40,7 +40,7 @@
#include "nctype.h"
#include "nasm.h"
-#include "float.h"
+#include "floats.h"
#include "error.h"
/*
diff --git a/asm/float.h b/asm/floats.h
index b07e542a..4f80acac 100644
--- a/asm/float.h
+++ b/asm/floats.h
@@ -32,12 +32,12 @@
* ----------------------------------------------------------------------- */
/*
- * float.h header file for the floating-point constant module of
- * the Netwide Assembler
+ * floats.h header file for the floating-point constant module of
+ * the Netwide Assembler
*/
-#ifndef NASM_FLOAT_H
-#define NASM_FLOAT_H
+#ifndef NASM_FLOATS_H
+#define NASM_FLOATS_H
#include "nasm.h"
@@ -51,4 +51,4 @@ enum float_round {
int float_const(const char *string, int sign, uint8_t *result, int bytes);
int float_option(const char *option);
-#endif
+#endif /* NASM_FLOATS_H */
diff --git a/asm/listing.c b/asm/listing.c
index 3101a258..f6ef6d1b 100644
--- a/asm/listing.c
+++ b/asm/listing.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2019 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2020 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -49,14 +49,6 @@
#define LIST_INDENT 40
#define LIST_HEXBIT 18
-typedef struct MacroInhibit MacroInhibit;
-
-static struct MacroInhibit {
- MacroInhibit *next;
- int level;
- int inhibiting;
-} *mistack;
-
static const char xdigit[] = "0123456789ABCDEF";
#define HEX(a,b) (*(a)=xdigit[((b)>>4)&15],(a)[1]=xdigit[(b)&15]);
@@ -135,12 +127,6 @@ static void list_cleanup(void)
if (!listfp)
return;
- while (mistack) {
- MacroInhibit *temp = mistack;
- mistack = temp->next;
- nasm_free(temp);
- }
-
list_emit();
fclose(listfp);
listfp = NULL;
@@ -148,6 +134,8 @@ static void list_cleanup(void)
static void list_init(const char *fname)
{
+ enum file_flags flags = NF_TEXT;
+
if (listfp)
list_cleanup();
@@ -156,7 +144,10 @@ static void list_init(const char *fname)
return;
}
- listfp = nasm_open_write(fname, NF_TEXT);
+ if (list_option('w'))
+ flags |= NF_IOLBF;
+
+ listfp = nasm_open_write(fname, flags);
if (!listfp) {
nasm_nonfatal("unable to open listing file `%s'", fname);
return;
@@ -167,10 +158,6 @@ static void list_init(const char *fname)
list_errors = NULL;
listlevel = 0;
suppress = 0;
- nasm_new(mistack);
- mistack->next = NULL;
- mistack->level = 0;
- mistack->inhibiting = true;
}
static void list_out(int64_t offset, char *str)
@@ -271,8 +258,13 @@ static void list_output(const struct out_data *data)
break;
case OUT_RESERVE:
{
- if (size)
+ if (size > 8) {
list_size(offset, "res", size);
+ } else {
+ memset(q, '?', size << 1);
+ q[size << 1] = '\0';
+ list_out(offset, q);
+ }
break;
}
default:
@@ -282,21 +274,14 @@ static void list_output(const struct out_data *data)
static void list_line(int type, int32_t lineno, const char *line)
{
+ (void)type;
+
if (!listfp)
return;
if (user_nolist)
return;
- if (mistack && mistack->inhibiting) {
- if (type == LIST_MACRO)
- return;
- else { /* pop the m i stack */
- MacroInhibit *temp = mistack;
- mistack = temp->next;
- nasm_free(temp);
- }
- }
list_emit();
if (lineno >= 0)
listlineno = lineno;
@@ -306,15 +291,6 @@ static void list_line(int type, int32_t lineno, const char *line)
listlevel_e = listlevel;
}
-static void mistack_push(bool inhibiting)
-{
- MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
- temp->next = mistack;
- temp->level = listlevel;
- temp->inhibiting = inhibiting;
- mistack = temp;
-}
-
static void list_uplevel(int type, int64_t size)
{
if (!listfp)
@@ -333,13 +309,6 @@ static void list_uplevel(int type, int64_t size)
case LIST_INCLUDE:
listlevel++;
- if (mistack && mistack->inhibiting)
- mistack_push(false);
- break;
-
- case LIST_MACRO_NOLIST:
- listlevel++;
- mistack_push(true);
break;
default:
@@ -364,11 +333,6 @@ static void list_downlevel(int type)
default:
listlevel--;
- while (mistack && mistack->level > listlevel) {
- MacroInhibit *temp = mistack;
- mistack = temp->next;
- nasm_free(temp);
- }
break;
}
}
diff --git a/asm/nasm.c b/asm/nasm.c
index 07a360b2..69a3db55 100644
--- a/asm/nasm.c
+++ b/asm/nasm.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2018 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2020 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -44,7 +44,7 @@
#include "error.h"
#include "saa.h"
#include "raa.h"
-#include "float.h"
+#include "floats.h"
#include "stdscan.h"
#include "insns.h"
#include "preproc.h"
@@ -55,6 +55,7 @@
#include "outform.h"
#include "listing.h"
#include "iflag.h"
+#include "quote.h"
#include "ver.h"
/*
@@ -87,6 +88,7 @@ static const struct error_format errfmt_gnu = { ":", "", ": " };
static const struct error_format errfmt_msvc = { "(", ")", " : " };
static const struct error_format *errfmt = &errfmt_gnu;
static struct strlist *warn_list;
+static struct nasm_errhold *errhold_stack;
unsigned int debug_nasm; /* Debugging messages? */
@@ -192,15 +194,27 @@ static const struct limit_info limit_info[LIMIT_MAX+1] = {
{ "macro-tokens", "tokens processed during single-lime macro expansion", 10000000 },
{ "mmacros", "multi-line macros before final return", 100000 },
{ "rep", "%rep count", 1000000 },
- { "eval", "expression evaluation descent", 1000000},
+ { "eval", "expression evaluation descent", 8192 },
{ "lines", "total source lines processed", 2000000000 }
};
static void set_default_limits(void)
{
int i;
+ size_t rl;
+ int64_t new_limit;
+
for (i = 0; i <= LIMIT_MAX; i++)
nasm_limit[i] = limit_info[i].default_val;
+
+ /*
+ * Try to set a sensible default value for the eval depth based
+ * on the limit of the stack size, if knowable...
+ */
+ rl = nasm_get_stack_size_limit();
+ new_limit = rl / (128 * sizeof(void *)); /* Sensible heuristic */
+ if (new_limit < nasm_limit[LIMIT_EVAL])
+ nasm_limit[LIMIT_EVAL] = new_limit;
}
enum directive_result
@@ -279,15 +293,6 @@ static void increment_offset(int64_t delta)
set_curr_offs(location.offset);
}
-static void nasm_fputs(const char *line, FILE * outfile)
-{
- if (outfile) {
- fputs(line, outfile);
- putc('\n', outfile);
- } else
- puts(line);
-}
-
/*
* Define system-defined macros that are not part of
* macros/standard.mac.
@@ -436,6 +441,46 @@ static int64_t make_posix_time(const struct tm *tm)
return t;
}
+/*
+ * Quote a filename string if and only if it is necessary.
+ * It is considered necessary if any one of these is true:
+ * 1. The filename contains control characters;
+ * 2. The filename starts or ends with a space or quote mark;
+ * 3. The filename contains more than one space in a row;
+ * 4. The filename is empty.
+ *
+ * The filename is returned in a newly allocated buffer.
+ */
+static char *nasm_quote_filename(const char *fn)
+{
+ const unsigned char *p =
+ (const unsigned char *)fn;
+
+ if (!p || !*p)
+ return nasm_strdup("\"\"");
+
+ if (*p <= ' ' || nasm_isquote(*p)) {
+ goto quote;
+ } else {
+ unsigned char cutoff = ' ';
+
+ while (*p) {
+ if (*p < cutoff)
+ goto quote;
+ cutoff = ' ' + (*p == ' ');
+ p++;
+ }
+ if (p[-1] <= ' ' || nasm_isquote(p[-1]))
+ goto quote;
+ }
+
+ /* Quoting not necessary */
+ return nasm_strdup(fn);
+
+quote:
+ return nasm_quote(fn, NULL);
+}
+
static void timestamp(void)
{
struct compile_time * const oct = &official_compile_time;
@@ -582,41 +627,71 @@ int main(int argc, char **argv)
} else if (operating_mode & OP_PREPROCESS) {
char *line;
const char *file_name = NULL;
- int32_t prior_linnum = 0;
- int lineinc = 0;
+ char *quoted_file_name = nasm_quote_filename(file_name);
+ int32_t linnum = 0;
+ int32_t lineinc = 0;
+ FILE *out;
if (outname) {
ofile = nasm_open_write(outname, NF_TEXT);
if (!ofile)
nasm_fatal("unable to open output file `%s'", outname);
- } else
+ out = ofile;
+ } else {
ofile = NULL;
+ out = stdout;
+ }
location.known = false;
- _pass_type = PASS_FIRST; /* We emulate this assembly pass */
+ _pass_type = PASS_PREPROC;
preproc->reset(inname, PP_PREPROC, depend_list);
while ((line = preproc->getline())) {
/*
* We generate %line directives if needed for later programs
*/
- int32_t linnum = prior_linnum += lineinc;
- int altline = src_get(&linnum, &file_name);
- if (altline) {
- if (altline == 1 && lineinc == 1)
- nasm_fputs("", ofile);
- else {
- lineinc = (altline != -1 || lineinc != 1);
- fprintf(ofile ? ofile : stdout,
- "%%line %"PRId32"+%d %s\n", linnum, lineinc,
- file_name);
+ struct src_location where = src_where();
+ if (file_name != where.filename) {
+ file_name = where.filename;
+ linnum = -1; /* Force a new %line statement */
+ lineinc = file_name ? 1 : 0;
+ nasm_free(quoted_file_name);
+ quoted_file_name = nasm_quote_filename(file_name);
+ } else if (lineinc) {
+ if (linnum + lineinc == where.lineno) {
+ /* Add one blank line to account for increment */
+ fputc('\n', out);
+ linnum += lineinc;
+ } else if (linnum - lineinc == where.lineno) {
+ /*
+ * Standing still, probably a macro. Set increment
+ * to zero.
+ */
+ lineinc = 0;
}
- prior_linnum = linnum;
+ } else {
+ /* lineinc == 0 */
+ if (linnum + 1 == where.lineno)
+ lineinc = 1;
}
- nasm_fputs(line, ofile);
- nasm_free(line);
+
+ /* Skip blank lines if we will need a %line anyway */
+ if (linnum == -1 && !line[0])
+ continue;
+
+ if (linnum != where.lineno) {
+ fprintf(out, "%%line %"PRId32"%+"PRId32" %s\n",
+ where.lineno, lineinc, quoted_file_name);
+ }
+ linnum = where.lineno + lineinc;
+
+ fputs(line, out);
+ fputc('\n', out);
}
+
+ nasm_free(quoted_file_name);
+
preproc->cleanup_pass();
reset_warnings();
if (ofile)
@@ -1576,8 +1651,19 @@ static void assemble_file(const char *fname, struct strlist *depend_list)
while (!terminate_after_phase && !pass_final()) {
_passn++;
- if (pass_type() != PASS_OPT || !global_offset_changed)
+ switch (pass_type()) {
+ case PASS_INIT:
+ _pass_type = PASS_FIRST;
+ break;
+ case PASS_OPT:
+ if (global_offset_changed)
+ break; /* One more optimization pass */
+ /* fall through */
+ default:
_pass_type++;
+ break;
+ }
+
global_offset_changed = 0;
/*
@@ -1651,6 +1737,9 @@ static void assemble_file(const char *fname, struct strlist *depend_list)
preproc->cleanup_pass();
+ /* We better not be having an error hold still... */
+ nasm_assert(!errhold_stack);
+
if (global_offset_changed) {
switch (pass_type()) {
case PASS_OPT:
@@ -1752,8 +1841,12 @@ static bool skip_this_pass(errflags severity)
if (type == ERR_LISTMSG)
return true;
- /* This message not applicable unless pass_final */
- return (severity & ERR_PASS2) && !pass_final();
+ /*
+ * This message not applicable unless it is the last pass we are going
+ * to execute; this can be either the final code-generation pass or
+ * the single pass executed in preproc-only mode.
+ */
+ return (severity & ERR_PASS2) && !pass_final_or_preproc();
}
/**
@@ -1840,14 +1933,39 @@ static fatal_func die_hard(errflags true_type, errflags severity)
}
/*
+ * Returns the struct src_location appropriate for use, after some
+ * potential filename mangling.
+ */
+static struct src_location error_where(errflags severity)
+{
+ struct src_location where;
+
+ if (severity & ERR_NOFILE) {
+ where.filename = NULL;
+ where.lineno = 0;
+ } else {
+ where = src_where_error();
+
+ if (!where.filename) {
+ where.filename =
+ inname && inname[0] ? inname :
+ outname && outname[0] ? outname :
+ NULL;
+ where.lineno = 0;
+ }
+ }
+
+ return where;
+}
+
+/*
* error reporting for critical and panic errors: minimize
* the amount of system dependencies for getting a message out,
* and in particular try to avoid memory allocations.
*/
fatal_func nasm_verror_critical(errflags severity, const char *fmt, va_list args)
{
- const char *currentfile = no_file_name;
- int32_t lineno = 0;
+ struct src_location where;
errflags true_type = severity & ERR_MASK;
static bool been_here = false;
@@ -1856,22 +1974,15 @@ fatal_func nasm_verror_critical(errflags severity, const char *fmt, va_list args
been_here = true;
- if (!(severity & ERR_NOFILE)) {
- src_get(&lineno, &currentfile);
- if (!currentfile) {
- currentfile =
- inname && inname[0] ? inname :
- outname && outname[0] ? outname :
- no_file_name;
- lineno = 0;
- }
- }
+ where = error_where(severity);
+ if (!where.filename)
+ where.filename = no_file_name;
fputs(error_pfx_table[severity], error_file);
- fputs(currentfile, error_file);
- if (lineno) {
+ fputs(where.filename, error_file);
+ if (where.lineno) {
fprintf(error_file, "%s%"PRId32"%s",
- errfmt->beforeline, lineno, errfmt->afterline);
+ errfmt->beforeline, where.lineno, errfmt->afterline);
}
fputs(errfmt->beforemsg, error_file);
vfprintf(error_file, fmt, args);
@@ -1881,6 +1992,74 @@ fatal_func nasm_verror_critical(errflags severity, const char *fmt, va_list args
}
/**
+ * Stack of tentative error hold lists.
+ */
+struct nasm_errtext {
+ struct nasm_errtext *next;
+ char *msg; /* Owned by this structure */
+ struct src_location where; /* Owned by the srcfile system */
+ errflags severity;
+ errflags true_type;
+};
+struct nasm_errhold {
+ struct nasm_errhold *up;
+ struct nasm_errtext *head, **tail;
+};
+
+static void nasm_free_error(struct nasm_errtext *et)
+{
+ nasm_free(et->msg);
+ nasm_free(et);
+}
+
+static void nasm_issue_error(struct nasm_errtext *et);
+
+struct nasm_errhold *nasm_error_hold_push(void)
+{
+ struct nasm_errhold *eh;
+
+ nasm_new(eh);
+ eh->up = errhold_stack;
+ eh->tail = &eh->head;
+ errhold_stack = eh;
+
+ return eh;
+}
+
+void nasm_error_hold_pop(struct nasm_errhold *eh, bool issue)
+{
+ struct nasm_errtext *et, *etmp;
+
+ /* Allow calling with a null argument saying no hold in the first place */
+ if (!eh)
+ return;
+
+ /* This *must* be the current top of the errhold stack */
+ nasm_assert(eh == errhold_stack);
+
+ if (eh->head) {
+ if (issue) {
+ if (eh->up) {
+ /* Commit the current hold list to the previous level */
+ *eh->up->tail = eh->head;
+ eh->up->tail = eh->tail;
+ } else {
+ /* Issue errors */
+ list_for_each_safe(et, etmp, eh->head)
+ nasm_issue_error(et);
+ }
+ } else {
+ /* Free the list, drop errors */
+ list_for_each_safe(et, etmp, eh->head)
+ nasm_free_error(et);
+ }
+ }
+
+ errhold_stack = eh->up;
+ nasm_free(eh);
+}
+
+/**
* common error reporting
* This is the common back end of the error reporting schemes currently
* implemented. It prints the nature of the warning and then the
@@ -1892,13 +2071,8 @@ fatal_func nasm_verror_critical(errflags severity, const char *fmt, va_list args
*/
void nasm_verror(errflags severity, const char *fmt, va_list args)
{
- char msg[1024];
- char warnsuf[64];
- char linestr[64];
- const char *pfx;
+ struct nasm_errtext *et;
errflags true_type = true_error_type(severity);
- const char *currentfile = NULL;
- int32_t lineno = 0;
if (true_type >= ERR_CRITICAL)
nasm_verror_critical(severity, fmt, args);
@@ -1906,23 +2080,49 @@ void nasm_verror(errflags severity, const char *fmt, va_list args)
if (is_suppressed(severity))
return;
- if (!(severity & ERR_NOFILE)) {
- src_get(&lineno, &currentfile);
- if (!currentfile) {
- currentfile =
- inname && inname[0] ? inname :
- outname && outname[0] ? outname :
- NULL;
- lineno = 0;
- }
+ nasm_new(et);
+ et->severity = severity;
+ et->true_type = true_type;
+ et->msg = nasm_vasprintf(fmt, args);
+ et->where = error_where(severity);
+
+ if (errhold_stack && true_type <= ERR_NONFATAL) {
+ /* It is a tentative error */
+ *errhold_stack->tail = et;
+ errhold_stack->tail = &et->next;
+ } else {
+ nasm_issue_error(et);
}
+ /*
+ * Don't do this before then, if we do, we lose messages in the list
+ * file, as the list file is only generated in the last pass.
+ */
+ if (skip_this_pass(severity))
+ return;
+
+ if (!(severity & (ERR_HERE|ERR_PP_LISTMACRO)))
+ if (preproc)
+ preproc->error_list_macros(severity);
+}
+
+/*
+ * Actually print, list and take action on an error
+ */
+static void nasm_issue_error(struct nasm_errtext *et)
+{
+ const char *pfx;
+ char warnsuf[64]; /* Warning suffix */
+ char linestr[64]; /* Formatted line number if applicable */
+ const errflags severity = et->severity;
+ const errflags true_type = et->true_type;
+ const struct src_location where = et->where;
+
if (severity & ERR_NO_SEVERITY)
pfx = "";
else
pfx = error_pfx_table[true_type];
- vsnprintf(msg, sizeof msg, fmt, args);
*warnsuf = 0;
if ((severity & (ERR_MASK|ERR_HERE|ERR_PP_LISTMACRO)) == ERR_WARNING) {
/*
@@ -1935,32 +2135,32 @@ void nasm_verror(errflags severity, const char *fmt, va_list args)
}
*linestr = 0;
- if (lineno) {
+ if (where.lineno) {
snprintf(linestr, sizeof linestr, "%s%"PRId32"%s",
- errfmt->beforeline, lineno, errfmt->afterline);
+ errfmt->beforeline, where.lineno, errfmt->afterline);
}
if (!skip_this_pass(severity)) {
- const char *file = currentfile ? currentfile : no_file_name;
+ const char *file = where.filename ? where.filename : no_file_name;
const char *here = "";
- if (severity & ERR_HERE)
- here = currentfile ? " here" : " in an unknown location";
+ if (severity & ERR_HERE) {
+ here = where.filename ? " here" : " in an unknown location";
+ }
if (warn_list && true_type < ERR_NONFATAL &&
- !(pass_first() && (severity & ERR_PASS1)))
- {
+ !(pass_first() && (severity & ERR_PASS1))) {
/*
* Buffer up warnings until we either get an error
* or we are on the code-generation pass.
*/
strlist_printf(warn_list, "%s%s%s%s%s%s%s",
file, linestr, errfmt->beforemsg,
- pfx, msg, here, warnsuf);
+ pfx, et->msg, here, warnsuf);
} else {
/*
- * If we have buffered warnings, and this is a non-warning,
- * output them now.
+ * Actually output an error. If we have buffered
+ * warnings, and this is a non-warning, output them now.
*/
if (true_type >= ERR_NONFATAL && warn_list) {
strlist_write(warn_list, "\n", error_file);
@@ -1969,45 +2169,42 @@ void nasm_verror(errflags severity, const char *fmt, va_list args)
fprintf(error_file, "%s%s%s%s%s%s%s\n",
file, linestr, errfmt->beforemsg,
- pfx, msg, here, warnsuf);
-
+ pfx, et->msg, here, warnsuf);
}
}
/* Are we recursing from error_list_macros? */
if (severity & ERR_PP_LISTMACRO)
- return;
+ goto done;
/*
* Don't suppress this with skip_this_pass(), or we don't get
* pass1 or preprocessor warnings in the list file
*/
if (severity & ERR_HERE) {
- if (lineno)
+ if (where.lineno)
lfmt->error(severity, "%s%s at %s:%"PRId32"%s",
- pfx, msg, currentfile, lineno, warnsuf);
- else if (currentfile)
+ pfx, et->msg, where.filename, where.lineno, warnsuf);
+ else if (where.filename)
lfmt->error(severity, "%s%s in file %s%s",
- pfx, msg, currentfile, warnsuf);
+ pfx, et->msg, where.filename, warnsuf);
else
lfmt->error(severity, "%s%s in an unknown location%s",
- pfx, msg, warnsuf);
+ pfx, et->msg, warnsuf);
} else {
- lfmt->error(severity, "%s%s%s", pfx, msg, warnsuf);
+ lfmt->error(severity, "%s%s%s", pfx, et->msg, warnsuf);
}
if (skip_this_pass(severity))
- return;
-
- /* error_list_macros can for obvious reasons not work with ERR_HERE */
- if (!(severity & ERR_HERE))
- if (preproc)
- preproc->error_list_macros(severity);
+ goto done;
if (true_type >= ERR_FATAL)
die_hard(true_type, severity);
else if (true_type >= ERR_NONFATAL)
terminate_after_phase = true;
+
+done:
+ nasm_free_error(et);
}
static void usage(void)
@@ -2067,6 +2264,7 @@ static void help(FILE *out)
" -Lm show multi-line macro calls with expanded parmeters\n"
" -Lp output a list file every pass, in case of errors\n"
" -Ls show all single-line macro definitions\n"
+ " -Lw flush the output after every line\n"
" -L+ enable all listing options (very verbose!)\n"
"\n"
" -Oflags... optimize opcodes, immediates and branch offsets\n"
diff --git a/asm/parser.c b/asm/parser.c
index 15cfcdfa..47b46ecd 100644
--- a/asm/parser.c
+++ b/asm/parser.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2019 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2020 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -46,12 +46,12 @@
#include "stdscan.h"
#include "eval.h"
#include "parser.h"
-#include "float.h"
+#include "floats.h"
#include "assemble.h"
#include "tables.h"
-static int is_comma_next(void);
+static int end_expression_next(void);
static struct tokenval tokval;
@@ -234,7 +234,8 @@ static bool parse_braces(decoflags_t *decoflags)
}
}
-static inline const expr *next_expr(const expr *e, const expr **next_list)
+static inline unused_func
+const expr *next_expr(const expr *e, const expr **next_list)
{
e++;
if (!e->type) {
@@ -355,14 +356,15 @@ static void mref_set_optype(operand *op)
/*
* Convert an expression vector returned from evaluate() into an
- * extop structure. Return zero on success.
+ * extop structure. Return zero on success. Note that the eop
+ * already has dup and elem set, so we can't clear it here.
*/
-static int value_to_extop(expr * vect, extop *eop, int32_t myseg)
+static int value_to_extop(expr *vect, extop *eop, int32_t myseg)
{
eop->type = EOT_DB_NUMBER;
- eop->offset = 0;
- eop->segment = eop->wrt = NO_SEG;
- eop->relative = false;
+ eop->val.num.offset = 0;
+ eop->val.num.segment = eop->val.num.wrt = NO_SEG;
+ eop->val.num.relative = false;
for (; vect->type; vect++) {
if (!vect->value) /* zero term, safe to ignore */
@@ -376,25 +378,26 @@ static int value_to_extop(expr * vect, extop *eop, int32_t myseg)
if (vect->type == EXPR_SIMPLE) {
/* Simple number expression */
- eop->offset += vect->value;
+ eop->val.num.offset += vect->value;
continue;
}
- if (eop->wrt == NO_SEG && !eop->relative && vect->type == EXPR_WRT) {
+ if (eop->val.num.wrt == NO_SEG && !eop->val.num.relative &&
+ vect->type == EXPR_WRT) {
/* WRT term */
- eop->wrt = vect->value;
+ eop->val.num.wrt = vect->value;
continue;
}
- if (!eop->relative &&
+ if (!eop->val.num.relative &&
vect->type == EXPR_SEGBASE + myseg && vect->value == -1) {
/* Expression of the form: foo - $ */
- eop->relative = true;
+ eop->val.num.relative = true;
continue;
}
- if (eop->segment == NO_SEG && vect->type >= EXPR_SEGBASE &&
- vect->value == 1) {
- eop->segment = vect->type - EXPR_SEGBASE;
+ if (eop->val.num.segment == NO_SEG &&
+ vect->type >= EXPR_SEGBASE && vect->value == 1) {
+ eop->val.num.segment = vect->type - EXPR_SEGBASE;
continue;
}
@@ -406,6 +409,228 @@ static int value_to_extop(expr * vect, extop *eop, int32_t myseg)
return 0;
}
+/*
+ * Parse an extended expression, used by db et al. "elem" is the element
+ * size; initially comes from the specific opcode (e.g. db == 1) but
+ * can be overridden.
+ */
+static int parse_eops(extop **result, bool critical, int elem)
+{
+ extop *eop = NULL, *prev = NULL;
+ extop **tail = result;
+ int sign;
+ int i = tokval.t_type;
+ int oper_num = 0;
+ bool do_subexpr = false;
+
+ *tail = NULL;
+
+ /* End of string is obvious; ) ends a sub-expression list e.g. DUP */
+ for (i = tokval.t_type; i != TOKEN_EOS; i = stdscan(NULL, &tokval)) {
+ char endparen = ')'; /* Is a right paren the end of list? */
+
+ if (i == ')')
+ break;
+
+ if (!eop) {
+ nasm_new(eop);
+ eop->dup = 1;
+ eop->elem = elem;
+ do_subexpr = false;
+ }
+ sign = +1;
+
+ /*
+ * end_expression_next() here is to distinguish this from
+ * a string used as part of an expression...
+ */
+ if (i == TOKEN_QMARK) {
+ eop->type = EOT_DB_RESERVE;
+ } else if (do_subexpr && i == '(') {
+ extop *subexpr;
+
+ stdscan(NULL, &tokval); /* Skip paren */
+ if (parse_eops(&eop->val.subexpr, critical, eop->elem) < 0)
+ goto fail;
+
+ subexpr = eop->val.subexpr;
+ if (!subexpr) {
+ /* Subexpression is empty */
+ eop->type = EOT_NOTHING;
+ } else if (!subexpr->next) {
+ /* Subexpression is a single element, flatten */
+ eop->val = subexpr->val;
+ eop->type = subexpr->type;
+ eop->dup *= subexpr->dup;
+ nasm_free(subexpr);
+ } else {
+ eop->type = EOT_EXTOP;
+ }
+
+ /* We should have ended on a closing paren */
+ if (tokval.t_type != ')') {
+ nasm_nonfatal("expected `)' after subexpression, got `%s'",
+ i == TOKEN_EOS ?
+ "end of line" : tokval.t_charptr);
+ goto fail;
+ }
+ endparen = 0; /* This time the paren is not the end */
+ } else if (i == '%') {
+ /* %(expression_list) */
+ do_subexpr = true;
+ continue;
+ } else if (i == TOKEN_SIZE) {
+ /* Element size override */
+ eop->elem = tokval.t_inttwo;
+ do_subexpr = true;
+ continue;
+ } else if (i == TOKEN_STR && end_expression_next()) {
+ eop->type = EOT_DB_STRING;
+ eop->val.string.data = tokval.t_charptr;
+ eop->val.string.len = tokval.t_inttwo;
+ } else if (i == TOKEN_STRFUNC) {
+ bool parens = false;
+ const char *funcname = tokval.t_charptr;
+ enum strfunc func = tokval.t_integer;
+
+ i = stdscan(NULL, &tokval);
+ if (i == '(') {
+ parens = true;
+ endparen = 0;
+ i = stdscan(NULL, &tokval);
+ }
+ if (i != TOKEN_STR) {
+ nasm_nonfatal("%s must be followed by a string constant",
+ funcname);
+ eop->type = EOT_NOTHING;
+ } else {
+ eop->type = EOT_DB_STRING_FREE;
+ eop->val.string.len =
+ string_transform(tokval.t_charptr, tokval.t_inttwo,
+ &eop->val.string.data, func);
+ if (eop->val.string.len == (size_t)-1) {
+ nasm_nonfatal("invalid input string to %s", funcname);
+ eop->type = EOT_NOTHING;
+ }
+ }
+ if (parens && i && i != ')') {
+ i = stdscan(NULL, &tokval);
+ if (i != ')')
+ nasm_nonfatal("unterminated %s function", funcname);
+ }
+ } else if (i == '-' || i == '+') {
+ char *save = stdscan_get();
+ struct tokenval tmptok;
+
+ sign = (i == '-') ? -1 : 1;
+ if (stdscan(NULL, &tmptok) != TOKEN_FLOAT) {
+ stdscan_set(save);
+ goto is_expression;
+ } else {
+ tokval = tmptok;
+ goto is_float;
+ }
+ } else if (i == TOKEN_FLOAT) {
+ is_float:
+ eop->type = EOT_DB_FLOAT;
+
+ if (eop->elem > 16) {
+ nasm_nonfatal("no %d-bit floating-point format supported",
+ eop->elem << 3);
+ eop->val.string.len = 0;
+ } else if (eop->elem < 1) {
+ nasm_nonfatal("floating-point constant"
+ " encountered in unknown instruction");
+ /*
+ * fix suggested by Pedro Gimeno... original line was:
+ * eop->type = EOT_NOTHING;
+ */
+ eop->val.string.len = 0;
+ } else {
+ eop->val.string.len = eop->elem;
+
+ eop = nasm_realloc(eop, sizeof(extop) + eop->val.string.len);
+ eop->val.string.data = (char *)eop + sizeof(extop);
+ if (!float_const(tokval.t_charptr, sign,
+ (uint8_t *)eop->val.string.data,
+ eop->val.string.len))
+ eop->val.string.len = 0;
+ }
+ if (!eop->val.string.len)
+ eop->type = EOT_NOTHING;
+ } else {
+ /* anything else, assume it is an expression */
+ expr *value;
+
+ is_expression:
+ value = evaluate(stdscan, NULL, &tokval, NULL,
+ critical, NULL);
+ i = tokval.t_type;
+ if (!value) /* Error in evaluator */
+ goto fail;
+ if (tokval.t_flag & TFLAG_DUP) {
+ /* Expression followed by DUP */
+ if (!is_simple(value)) {
+ nasm_nonfatal("non-constant argument supplied to DUP");
+ goto fail;
+ } else if (value->value < 0) {
+ nasm_nonfatal("negative argument supplied to DUP");
+ goto fail;
+ }
+ eop->dup *= (size_t)value->value;
+ do_subexpr = true;
+ continue;
+ }
+ if (value_to_extop(value, eop, location.segment)) {
+ nasm_nonfatal("expression is not simple or relocatable");
+ }
+ }
+
+ if (eop->dup == 0 || eop->type == EOT_NOTHING) {
+ nasm_free(eop);
+ } else if (eop->type == EOT_DB_RESERVE &&
+ prev && prev->type == EOT_DB_RESERVE &&
+ prev->elem == eop->elem) {
+ /* Coalesce multiple EOT_DB_RESERVE */
+ prev->dup += eop->dup;
+ nasm_free(eop);
+ } else {
+ /* Add this eop to the end of the chain */
+ prev = eop;
+ *tail = eop;
+ tail = &eop->next;
+ }
+
+ oper_num++;
+ eop = NULL; /* Done with this operand */
+
+ /*
+ * We're about to call stdscan(), which will eat the
+ * comma that we're currently sitting on between
+ * arguments. However, we'd better check first that it
+ * _is_ a comma.
+ */
+ if (i == TOKEN_EOS || i == endparen) /* Already at end? */
+ break;
+ if (i != ',') {
+ i = stdscan(NULL, &tokval); /* eat the comma or final paren */
+ if (i == TOKEN_EOS || i == ')') /* got end of expression */
+ break;
+ if (i != ',') {
+ nasm_nonfatal("comma expected after operand");
+ goto fail;
+ }
+ }
+ }
+
+ return oper_num;
+
+fail:
+ if (eop)
+ nasm_free(eop);
+ return -1;
+}
+
insn *parse_line(char *buffer, insn *result)
{
bool insn_is_label = false;
@@ -562,141 +787,19 @@ restart_parse:
critical = pass_final() || (result->opcode == I_INCBIN);
if (opcode_is_db(result->opcode) || result->opcode == I_INCBIN) {
- extop *eop, **tail = &result->eops, **fixptr;
- int oper_num = 0;
- int32_t sign;
-
- result->eops_float = false;
-
- /*
- * Begin to read the DB/DW/DD/DQ/DT/DO/DY/DZ/INCBIN operands.
- */
- while (1) {
- i = stdscan(NULL, &tokval);
- if (i == TOKEN_EOS)
- break;
- else if (first && i == ':') {
- insn_is_label = true;
- goto restart_parse;
- }
- first = false;
- fixptr = tail;
- eop = *tail = nasm_malloc(sizeof(extop));
- tail = &eop->next;
- eop->next = NULL;
- eop->type = EOT_NOTHING;
- oper_num++;
- sign = +1;
-
- /*
- * is_comma_next() here is to distinguish this from
- * a string used as part of an expression...
- */
- if (i == TOKEN_STR && is_comma_next()) {
- eop->type = EOT_DB_STRING;
- eop->stringval = tokval.t_charptr;
- eop->stringlen = tokval.t_inttwo;
- i = stdscan(NULL, &tokval); /* eat the comma */
- } else if (i == TOKEN_STRFUNC) {
- bool parens = false;
- const char *funcname = tokval.t_charptr;
- enum strfunc func = tokval.t_integer;
- i = stdscan(NULL, &tokval);
- if (i == '(') {
- parens = true;
- i = stdscan(NULL, &tokval);
- }
- if (i != TOKEN_STR) {
- nasm_nonfatal("%s must be followed by a string constant",
- funcname);
- eop->type = EOT_NOTHING;
- } else {
- eop->type = EOT_DB_STRING_FREE;
- eop->stringlen =
- string_transform(tokval.t_charptr, tokval.t_inttwo,
- &eop->stringval, func);
- if (eop->stringlen == (size_t)-1) {
- nasm_nonfatal("invalid input string to %s", funcname);
- eop->type = EOT_NOTHING;
- }
- }
- if (parens && i && i != ')') {
- i = stdscan(NULL, &tokval);
- if (i != ')')
- nasm_nonfatal("unterminated %s function", funcname);
- }
- if (i && i != ',')
- i = stdscan(NULL, &tokval);
- } else if (i == '-' || i == '+') {
- char *save = stdscan_get();
- int token = i;
- sign = (i == '-') ? -1 : 1;
- i = stdscan(NULL, &tokval);
- if (i != TOKEN_FLOAT) {
- stdscan_set(save);
- i = tokval.t_type = token;
- goto is_expression;
- } else {
- goto is_float;
- }
- } else if (i == TOKEN_FLOAT) {
-is_float:
- eop->type = EOT_DB_STRING;
- result->eops_float = true;
-
- eop->stringlen = db_bytes(result->opcode);
- if (eop->stringlen > 16) {
- nasm_nonfatal("floating-point constant"
- " encountered in DY or DZ instruction");
- eop->stringlen = 0;
- } else if (eop->stringlen < 1) {
- nasm_nonfatal("floating-point constant"
- " encountered in unknown instruction");
- /*
- * fix suggested by Pedro Gimeno... original line was:
- * eop->type = EOT_NOTHING;
- */
- eop->stringlen = 0;
- }
-
- eop = nasm_realloc(eop, sizeof(extop) + eop->stringlen);
- tail = &eop->next;
- *fixptr = eop;
- eop->stringval = (char *)eop + sizeof(extop);
- if (!eop->stringlen ||
- !float_const(tokval.t_charptr, sign,
- (uint8_t *)eop->stringval, eop->stringlen))
- eop->type = EOT_NOTHING;
- i = stdscan(NULL, &tokval); /* eat the comma */
- } else {
- /* anything else, assume it is an expression */
- expr *value;
+ int oper_num;
-is_expression:
- value = evaluate(stdscan, NULL, &tokval, NULL,
- critical, NULL);
- i = tokval.t_type;
- if (!value) /* Error in evaluator */
- goto fail;
- if (value_to_extop(value, eop, location.segment)) {
- nasm_nonfatal("operand %d: expression is not simple or relocatable",
- oper_num);
- }
- }
+ i = stdscan(NULL, &tokval);
- /*
- * We're about to call stdscan(), which will eat the
- * comma that we're currently sitting on between
- * arguments. However, we'd better check first that it
- * _is_ a comma.
- */
- if (i == TOKEN_EOS) /* also could be EOL */
- break;
- if (i != ',') {
- nasm_nonfatal("comma expected after operand %d", oper_num);
- goto fail;
- }
+ if (first && i == ':') {
+ /* Really a label */
+ insn_is_label = true;
+ goto restart_parse;
}
+ first = false;
+ oper_num = parse_eops(&result->eops, critical, db_bytes(result->opcode));
+ if (oper_num < 0)
+ goto fail;
if (result->opcode == I_INCBIN) {
/*
@@ -724,11 +827,19 @@ is_expression:
* Throw the instruction away.
*/
goto fail;
- } else /* DB ... */ if (oper_num == 0)
- nasm_warn(WARN_OTHER, "no operand for data declaration");
- else
+ } else {
+ /* DB et al */
result->operands = oper_num;
-
+ if (oper_num == 0)
+ /*!
+ *!db-empty [on] no operand for data declaration
+ *! warns about a \c{DB}, \c{DW}, etc declaration
+ *! with no operands, producing no output.
+ *! This is permitted, but often indicative of an error.
+ *! See \k{db}.
+ */
+ nasm_warn(WARN_DB_EMPTY, "no operand for data declaration");
+ }
return result;
}
@@ -1197,7 +1308,7 @@ fail:
return result;
}
-static int is_comma_next(void)
+static int end_expression_next(void)
{
struct tokenval tv;
char *p;
@@ -1207,17 +1318,34 @@ static int is_comma_next(void)
i = stdscan(NULL, &tv);
stdscan_set(p);
- return (i == ',' || i == ';' || !i);
+ return (i == ',' || i == ';' || i == ')' || !i);
}
-void cleanup_insn(insn * i)
+static void free_eops(extop *e)
{
- extop *e;
+ extop *next;
+
+ while (e) {
+ next = e->next;
+ switch (e->type) {
+ case EOT_EXTOP:
+ free_eops(e->val.subexpr);
+ break;
+
+ case EOT_DB_STRING_FREE:
+ nasm_free(e->val.string.data);
+ break;
+
+ default:
+ break;
+ }
- while ((e = i->eops)) {
- i->eops = e->next;
- if (e->type == EOT_DB_STRING_FREE)
- nasm_free(e->stringval);
nasm_free(e);
+ e = next;
}
}
+
+void cleanup_insn(insn * i)
+{
+ free_eops(i->eops);
+}
diff --git a/asm/pptok.dat b/asm/pptok.dat
index 8b90c5b2..8013428d 100644
--- a/asm/pptok.dat
+++ b/asm/pptok.dat
@@ -45,6 +45,7 @@
*
*ctx
*def
+*defalias
*empty
*env
*id
@@ -94,6 +95,7 @@
%push
%rep
%repl
+%require
%rotate
%stacksize
%undef
diff --git a/asm/pptok.pl b/asm/pptok.pl
index a4853f2e..5498cb46 100755
--- a/asm/pptok.pl
+++ b/asm/pptok.pl
@@ -223,19 +223,19 @@ if ($what eq 'c') {
# Put a large value in unused slots. This makes it extremely unlikely
# that any combination that involves unused slot will pass the range test.
# This speeds up rejection of unrecognized tokens, i.e. identifiers.
- print OUT "#define UNUSED (65535/3)\n";
+ print OUT "#define UNUSED_HASH_ENTRY (65535/3)\n";
print OUT " static const int16_t hash1[$n] = {\n";
for ($i = 0; $i < $n; $i++) {
my $h = ${$g}[$i*2+0];
- print OUT " ", defined($h) ? $h : 'UNUSED', ",\n";
+ print OUT " ", defined($h) ? $h : 'UNUSED_HASH_ENTRY', ",\n";
}
print OUT " };\n";
print OUT " static const int16_t hash2[$n] = {\n";
for ($i = 0; $i < $n; $i++) {
my $h = ${$g}[$i*2+1];
- print OUT " ", defined($h) ? $h : 'UNUSED', ",\n";
+ print OUT " ", defined($h) ? $h : 'UNUSED_HASH_ENTRY', ",\n";
}
print OUT " };\n";
diff --git a/asm/preproc.c b/asm/preproc.c
index e5126b77..2bc95d34 100644
--- a/asm/preproc.c
+++ b/asm/preproc.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2019 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2020 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -76,6 +76,16 @@
#include "tables.h"
#include "listing.h"
+/*
+ * Preprocessor execution options that can be controlled by %pragma or
+ * other directives. This structure is initialized to zero on each
+ * pass; this *must* reflect the default initial state.
+ */
+static struct pp_opts {
+ bool noaliases;
+ bool sane_empty_expansion;
+} ppopt;
+
typedef struct SMacro SMacro;
typedef struct MMacro MMacro;
typedef struct MMacroInvocation MMacroInvocation;
@@ -99,10 +109,12 @@ typedef struct Cond Cond;
* tok_smac_param(0) but the one representing `y' will be
* tok_smac_param(1); see the accessor functions below.
*
- * TOK_INTERNAL_STRING is a dirty hack: it's a single string token
- * which doesn't need quotes around it. Used in the pre-include
- * mechanism as an alternative to trying to find a sensible type of
- * quote to use on the filename we were passed.
+ * TOK_INTERNAL_STRING is a string which has been unquoted, but should
+ * be treated as if it was a quoted string. The code is free to change
+ * one into the other at will. TOK_NAKED_STRING is a text token which
+ * should be treated as a string, but which MUST NOT be turned into a
+ * quoted string. TOK_INTERNAL_STRINGs can contain any character,
+ * including NUL, but TOK_NAKED_STRING must be a valid C string.
*/
enum pp_token_type {
TOK_NONE = 0, TOK_WHITESPACE, TOK_COMMENT,
@@ -112,11 +124,12 @@ enum pp_token_type {
TOK_PREPROC_ID, TOK_MMACRO_PARAM, TOK_LOCAL_SYMBOL,
TOK_LOCAL_MACRO, TOK_ENVIRON, TOK_STRING,
TOK_NUMBER, TOK_FLOAT, TOK_OTHER,
- TOK_INTERNAL_STRING,
+ TOK_INTERNAL_STRING, TOK_NAKED_STRING,
TOK_PREPROC_Q, TOK_PREPROC_QQ,
TOK_PASTE, /* %+ */
TOK_COND_COMMA, /* %, */
TOK_INDIRECT, /* %[...] */
+ TOK_XDEF_PARAM, /* Used during %xdefine processing */
TOK_SMAC_START_PARAMS, /* MUST BE LAST IN THE LIST!!! */
TOK_MAX = INT_MAX /* Keep compiler from reducing the range */
};
@@ -218,6 +231,17 @@ struct SMacro {
};
/*
+ * "No listing" flags. Inside a loop (%rep..%endrep) we may have
+ * macro listing suppressed with .nolist, but we still need to
+ * update line numbers for error messages and debug information...
+ * unless we are nested inside an actual .nolist macro.
+ */
+enum nolist_flags {
+ NL_LIST = 1, /* Suppress list output */
+ NL_LINE = 2 /* Don't update line information */
+};
+
+/*
* Store the definition of a multi-line macro. This is also used to
* store the interiors of `%rep...%endrep' blocks, which are
* effectively self-re-invoking multi-line macros which simply
@@ -259,9 +283,9 @@ struct MMacro {
#endif
char *name;
int nparam_min, nparam_max;
+ enum nolist_flags nolist; /* is this macro listing-inhibited? */
bool casesense;
bool plus; /* is the last parameter greedy? */
- bool nolist; /* is this macro listing-inhibited? */
bool capture_label; /* macro definition has %00; capture label */
bool in_progress; /* is this macro currently being expanded? */
int32_t max_depth; /* maximum number of recursive expansions allowed */
@@ -280,15 +304,12 @@ struct MMacro {
struct mstk dstk; /* Macro definitions stack */
Token **params; /* actual parameters */
Token *iline; /* invocation line */
+ struct src_location where; /* location of definition */
unsigned int nparam, rotate;
char *iname; /* name invoked as */
int *paramlen;
uint64_t unique;
- int lineno; /* Current line number on expansion */
uint64_t condcnt; /* number of if blocks... */
-
- const char *fname; /* File where defined */
- int32_t xline; /* First line in macro */
};
@@ -344,6 +365,17 @@ static inline unsigned int tok_check_len(size_t len)
return len;
}
+static inline bool tok_text_match(const struct Token *a, const struct Token *b)
+{
+ return a->len == b->len && !memcmp(tok_text(a), tok_text(b), a->len);
+}
+
+static inline unused_func bool
+tok_match(const struct Token *a, const struct Token *b)
+{
+ return a->type == b->type && tok_text_match(a, b);
+}
+
/* strlen() variant useful for set_text() and its variants */
static size_t tok_strlen(const char *str)
{
@@ -361,12 +393,13 @@ static Token *set_text(struct Token *t, const char *text, size_t len)
if (t->len > INLINE_TEXT)
nasm_free(t->text.p.ptr);
- nasm_zero(t->text.a);
+ nasm_zero(t->text);
- t->len = tok_check_len(len);
+ t->len = len = tok_check_len(len);
textp = (len > INLINE_TEXT)
? (t->text.p.ptr = nasm_malloc(len+1)) : t->text.a;
- memcpy(textp, text, len+1);
+ memcpy(textp, text, len);
+ textp[len] = '\0';
return t;
}
@@ -376,18 +409,21 @@ static Token *set_text(struct Token *t, const char *text, size_t len)
*/
static Token *set_text_free(struct Token *t, char *text, unsigned int len)
{
+ char *textp;
+
if (t->len > INLINE_TEXT)
nasm_free(t->text.p.ptr);
- nasm_zero(t->text.a);
+ nasm_zero(t->text);
- t->len = tok_check_len(len);
+ t->len = len = tok_check_len(len);
if (len > INLINE_TEXT) {
- t->text.p.ptr = text;
+ textp = t->text.p.ptr = text;
} else {
- memcpy(t->text.a, text, len+1);
+ textp = memcpy(t->text.a, text, len);
nasm_free(text);
}
+ textp[len] = '\0';
return t;
}
@@ -430,22 +466,29 @@ struct Line {
Line *next;
MMacro *finishes;
Token *first;
+ struct src_location where; /* Where defined */
};
/*
* To handle an arbitrary level of file inclusion, we maintain a
* stack (ie linked list) of these things.
+ *
+ * Note: when we issue a message for a continuation line, we want to
+ * issue it for the actual *start* of the continuation line. This means
+ * we need to remember how many lines to skip over for the next one.
*/
struct Include {
Include *next;
FILE *fp;
Cond *conds;
Line *expansion;
- const char *fname;
+ uint64_t nolist; /* Listing inhibit counter */
+ uint64_t noline; /* Line number update inhibit counter */
struct mstk mstk;
MMacro *popping; /* Ignore all until this is popped from mstk.mstk */
- int lineno, lineinc;
- bool nolist;
+ struct src_location where; /* Filename and current line number */
+ int32_t lineinc; /* Increment given by %line */
+ int32_t lineskip; /* Accounting for passed continuation lines */
};
/*
@@ -569,7 +612,6 @@ static int LocalOffset = 0;
static Context *cstk;
static Include *istk;
static const struct strlist *ipath_list;
-static bool do_aliases;
static struct strlist *deplist;
@@ -635,6 +677,7 @@ static Token *expand_id(Token * tline);
static Context *get_ctx(const char *name, const char **namep);
static Token *make_tok_num(Token *next, int64_t val);
static Token *make_tok_qstr(Token *next, const char *str);
+static Token *make_tok_qstr_len(Token *next, const char *str, size_t len);
static Token *make_tok_char(Token *next, char op);
static Token *new_Token(Token * next, enum pp_token_type type,
const char *text, size_t txtlen);
@@ -646,6 +689,8 @@ static Token *delete_Token(Token *t);
static Token *steal_Token(Token *dst, Token *src);
static const struct use_package *
get_use_pkg(Token *t, const char *dname, const char **name);
+static void mark_smac_params(Token *tline, const SMacro *tmpl,
+ enum pp_token_type type);
/* Safe test for token type, false on x == NULL */
static inline bool tok_type(const Token *x, enum pp_token_type t)
@@ -723,6 +768,10 @@ static const char *unquote_token(Token *t)
}
}
+/*
+ * Same as unquote_token(), but error out if the resulting string
+ * contains unacceptable control characters.
+ */
static const char *unquote_token_cstr(Token *t)
{
if (t->type != TOK_STRING)
@@ -749,7 +798,25 @@ static const char *unquote_token_cstr(Token *t)
}
}
-static Token *quote_internal_string_token(Token *t)
+/*
+ * Convert a TOK_INTERNAL_STRING token to a quoted
+ * TOK_STRING tokens.
+ */
+static Token *quote_any_token(Token *t);
+static inline unused_func
+Token *quote_token(Token *t)
+{
+ if (likely(!tok_is(t, TOK_INTERNAL_STRING)))
+ return t;
+
+ return quote_any_token(t);
+}
+
+/*
+ * Convert *any* kind of token to a quoted
+ * TOK_STRING token.
+ */
+static Token *quote_any_token(Token *t)
{
size_t len;
char *p;
@@ -759,14 +826,6 @@ static Token *quote_internal_string_token(Token *t)
return set_text_free(t, p, len);
}
-static inline Token *quote_token(Token *t)
-{
- if (likely(!tok_is(t, TOK_INTERNAL_STRING)))
- return t;
-
- return quote_internal_string_token(t);
-}
-
/*
* In-place reverse a list of tokens.
*/
@@ -809,6 +868,7 @@ static const char *pp_getenv(const Token *t, bool warn)
break;
case TOK_INTERNAL_STRING:
+ case TOK_NAKED_STRING:
case TOK_ID:
is_string = false;
break;
@@ -1071,21 +1131,53 @@ static void free_smacro(SMacro *s)
}
/*
- * Free all currently defined macros, and free the hash tables
+ * Free all currently defined macros, and free the hash tables if empty
*/
-static void free_smacro_table(struct hash_table *smt)
+enum clear_what {
+ CLEAR_NONE = 0,
+ CLEAR_DEFINE = 1, /* Clear smacros */
+ CLEAR_DEFALIAS = 2, /* Clear smacro aliases */
+ CLEAR_ALLDEFINE = CLEAR_DEFINE|CLEAR_DEFALIAS,
+ CLEAR_MMACRO = 4,
+ CLEAR_ALL = CLEAR_ALLDEFINE|CLEAR_MMACRO
+};
+
+static void clear_smacro_table(struct hash_table *smt, enum clear_what what)
{
struct hash_iterator it;
const struct hash_node *np;
+ bool empty = true;
+ /*
+ * Walk the hash table and clear out anything we don't want
+ */
hash_for_each(smt, it, np) {
SMacro *tmp;
SMacro *s = np->data;
- nasm_free((void *)np->key);
- list_for_each_safe(s, tmp, s)
- free_smacro(s);
+ SMacro **head = (SMacro **)&np->data;
+
+ list_for_each_safe(s, tmp, s) {
+ if (what & ((enum clear_what)s->alias + 1)) {
+ *head = s->next;
+ free_smacro(s);
+ } else {
+ empty = false;
+ }
+ }
}
- hash_free(smt);
+
+ /*
+ * Free the hash table and keys if and only if it is now empty.
+ * Note: we cannot free keys even for an empty list above, as that
+ * mucks up the hash algorithm.
+ */
+ if (empty)
+ hash_free_all(smt, true);
+}
+
+static void free_smacro_table(struct hash_table *smt)
+{
+ clear_smacro_table(smt, CLEAR_ALLDEFINE);
}
static void free_mmacro_table(struct hash_table *mmt)
@@ -1245,10 +1337,12 @@ static char *line_from_file(FILE *f)
unsigned int size, next;
const unsigned int delta = 512;
const unsigned int pad = 8;
- unsigned int nr_cont = 0;
bool cont = false;
char *buffer, *p;
- int32_t lineno;
+
+ istk->where.lineno += istk->lineskip + istk->lineinc;
+ src_set_linnum(istk->where.lineno);
+ istk->lineskip = 0;
size = delta;
p = buffer = nasm_malloc(size);
@@ -1293,7 +1387,7 @@ static char *line_from_file(FILE *f)
ungetc(next, f);
if (next == '\r' || next == '\n') {
cont = true;
- nr_cont++;
+ istk->lineskip += istk->lineinc;
continue;
}
break;
@@ -1308,10 +1402,6 @@ static char *line_from_file(FILE *f)
*p++ = c;
} while (c);
- lineno = src_get_linnum() + istk->lineinc +
- (nr_cont * istk->lineinc);
- src_set_linnum(lineno);
-
return buffer;
}
@@ -1331,8 +1421,8 @@ static char *read_line(void)
if (!line)
return NULL;
- if (!istk->nolist)
- lfmt->line(LIST_READ, src_get_linnum(), line);
+ if (!istk->nolist)
+ lfmt->line(LIST_READ, istk->where.lineno, line);
return line;
}
@@ -1914,7 +2004,7 @@ static char *detoken(Token * tlist, bool expand_locals)
{
const char *v = pp_getenv(t, true);
set_text(t, v, tok_strlen(v));
- t->type = TOK_INTERNAL_STRING;
+ t->type = TOK_NAKED_STRING;
break;
}
@@ -2154,10 +2244,11 @@ static Context *get_ctx(const char *name, const char **namep)
* the end of the path.
*
* Note: for INC_PROBE the function returns NULL at all times;
- * instead look for the
+ * instead look for a filename in *slpath.
*/
enum incopen_mode {
INC_NEEDED, /* File must exist */
+ INC_REQUIRED, /* File must exist, but only open once/pass */
INC_OPTIONAL, /* Missing is OK */
INC_PROBE /* Only an existence probe */
};
@@ -2202,45 +2293,98 @@ static FILE *inc_fopen_search(const char *file, char **slpath,
* Open a file, or test for the presence of one (depending on omode),
* considering the include path.
*/
+struct file_hash_entry {
+ const char *path;
+ struct file_hash_entry *full; /* Hash entry for the full path */
+ int64_t include_pass; /* Pass in which last included (for %require) */
+};
+
static FILE *inc_fopen(const char *file,
struct strlist *dhead,
const char **found_path,
enum incopen_mode omode,
enum file_flags fmode)
{
+ struct file_hash_entry **fhep;
+ struct file_hash_entry *fhe = NULL;
struct hash_insert hi;
- void **hp;
- char *path;
+ const char *path = NULL;
FILE *fp = NULL;
-
- hp = hash_find(&FileHash, file, &hi);
- if (hp) {
- path = *hp;
- if (path || omode != INC_NEEDED) {
- strlist_add(dhead, path ? path : file);
+ const int64_t pass = pass_count();
+ bool skip_open = (omode == INC_PROBE);
+
+ fhep = (struct file_hash_entry **)hash_find(&FileHash, file, &hi);
+ if (fhep) {
+ fhe = *fhep;
+ if (fhe) {
+ path = fhe->path;
+ skip_open |= (omode == INC_REQUIRED) &&
+ (fhe->full->include_pass >= pass);
}
} else {
/* Need to do the actual path search */
- fp = inc_fopen_search(file, &path, omode, fmode);
+ char *pptr;
+ fp = inc_fopen_search(file, &pptr, omode, fmode);
+ path = pptr;
/* Positive or negative result */
- hash_add(&hi, nasm_strdup(file), path);
+ if (path) {
+ nasm_new(fhe);
+ fhe->path = path;
+ fhe->full = fhe; /* It is *possible*... */
+ }
+ hash_add(&hi, nasm_strdup(file), fhe);
+
+ /*
+ * Add a hash entry for the canonical path if there isn't one
+ * already. Try to get the unique name from the OS best we can.
+ * Note that ->path and ->full->path can be different, and that
+ * is okay (we don't want to print out a full canonical path
+ * in messages, for example.)
+ */
+ if (path) {
+ char *fullpath = nasm_realpath(path);
+
+ if (!strcmp(file, fullpath)) {
+ nasm_free(fullpath);
+ } else {
+ struct file_hash_entry **fullp, *full;
+ fullp = (struct file_hash_entry **)
+ hash_find(&FileHash, fullpath, &hi);
+
+ if (fullp) {
+ full = *fullp;
+ nasm_free(fullpath);
+ } else {
+ nasm_new(full);
+ full->path = fullpath;
+ full->full = full;
+ hash_add(&hi, path, full);
+ }
+ fhe->full = full;
+ }
+ }
/*
* Add file to dependency path.
*/
- if (path || omode != INC_NEEDED)
- strlist_add(dhead, file);
+ strlist_add(dhead, path ? path : file);
}
- if (!path) {
- if (omode == INC_NEEDED)
- nasm_fatal("unable to open include file `%s'", file);
- } else {
- if (!fp && omode != INC_PROBE)
- fp = nasm_open_read(path, fmode);
+ if (path && !fp && omode != INC_PROBE)
+ fp = nasm_open_read(path, fmode);
+
+ if (omode < INC_OPTIONAL && !fp) {
+ if (!path)
+ errno = ENOENT;
+
+ nasm_nonfatal("unable to open include file `%s': %s",
+ file, strerror(errno));
}
+ if (fp)
+ fhe->full->include_pass = pass;
+
if (found_path)
*found_path = path;
@@ -2272,30 +2416,15 @@ FILE *pp_input_fopen(const char *filename, enum file_flags mode)
*
* Note that this is also called with nparam zero to resolve
* `ifdef'.
- *
- * If you already know which context macro belongs to, you can pass
- * the context pointer as first parameter; if you won't but name begins
- * with %$ the context will be automatically computed. If all_contexts
- * is true, macro will be searched in outer contexts as well.
*/
static bool
-smacro_defined(Context * ctx, const char *name, int nparam, SMacro ** defn,
+smacro_defined(Context *ctx, const char *name, int nparam, SMacro **defn,
bool nocase, bool find_alias)
{
struct hash_table *smtbl;
SMacro *m;
- if (ctx) {
- smtbl = &ctx->localmac;
- } else if (name[0] == '%' && name[1] == '$') {
- if (cstk)
- ctx = get_ctx(name, &name);
- if (!ctx)
- return false; /* got to return _something_ */
- smtbl = &ctx->localmac;
- } else {
- smtbl = &smacros;
- }
+ smtbl = ctx ? &ctx->localmac : &smacros;
restart:
m = (SMacro *) hash_findix(smtbl, name);
@@ -2305,7 +2434,7 @@ restart:
(nparam <= 0 || m->nparam == 0 || nparam == m->nparam ||
(m->greedy && nparam >= m->nparam-1))) {
if (m->alias && !find_alias) {
- if (do_aliases) {
+ if (!ppopt.noaliases) {
name = tok_text(m->expansion);
goto restart;
} else {
@@ -2347,54 +2476,77 @@ static int read_param_count(const char *str)
*
* Note that we need space in the params array for parameter 0 being
* a possible captured label as well as the final NULL.
+ *
+ * Returns a pointer to the pointer to a terminal comma if present;
+ * used to drop an empty terminal argument for legacy reasons.
*/
-static void count_mmac_params(Token * t, int *nparamp, Token ***paramsp)
+static Token **count_mmac_params(Token *tline, int *nparamp, Token ***paramsp)
{
int paramsize;
int nparam = 0;
+ Token *t;
+ Token **comma = NULL, **maybe_comma = NULL;
Token **params;
paramsize = PARAM_DELTA;
- params = nasm_malloc(paramsize * sizeof(*params));
- params[0] = NULL;
-
- while ((t = skip_white(t))) {
- /* 2 slots for captured label and NULL */
- if (nparam+2 >= paramsize) {
- paramsize += PARAM_DELTA;
- params = nasm_realloc(params, sizeof(*params) * paramsize);
- }
- params[++nparam] = t;
- if (tok_is(t, '{')) {
- int brace = 1;
- while (brace && (t = t->next)) {
- brace += tok_is(t, '{');
- brace -= tok_is(t, '}');
+ nasm_newn(params, paramsize);
+
+ t = skip_white(tline);
+ if (t) {
+ while (true) {
+ /* Need two slots for captured label and NULL */
+ if (unlikely(nparam+2 >= paramsize)) {
+ paramsize += PARAM_DELTA;
+ params = nasm_realloc(params, sizeof(*params) * paramsize);
+ }
+ params[++nparam] = t;
+ if (tok_is(t, '{')) {
+ int brace = 1;
+
+ comma = NULL; /* Non-empty parameter */
+
+ while (brace && (t = t->next)) {
+ brace += tok_is(t, '{');
+ brace -= tok_is(t, '}');
+ }
+
+ if (t) {
+ /*
+ * Now we've found the closing brace, look further
+ * for the comma.
+ */
+ t = skip_white(t->next);
+ if (tok_isnt(t, ','))
+ nasm_nonfatal("braces do not enclose all of macro parameter");
+ } else {
+ nasm_nonfatal("expecting closing brace in macro parameter");
+ }
}
+ /* Advance to the next comma */
if (t) {
- /*
- * Now we've found the closing brace, look further
- * for the comma.
- */
- t = skip_white(t->next);
- if (tok_isnt(t, ','))
- nasm_nonfatal("braces do not enclose all of macro parameter");
- } else {
- nasm_nonfatal("expecting closing brace in macro parameter");
+ maybe_comma = &t->next;
+ while (tok_isnt(t, ',')) {
+ if (!tok_white(t))
+ comma = NULL; /* Non-empty parameter */
+ maybe_comma = &t->next;
+ t = t->next;
+ }
}
- }
- while (tok_isnt(t, ','))
- t = t->next;
+ if (!t)
+ break; /* End of string, no comma */
- if (t) /* got a comma */
- t = t->next; /* eat the comma */
+ comma = maybe_comma; /* Point to comma pointer */
+ t = skip_white(t->next); /* Eat the comma and whitespace */
+ }
}
params[nparam+1] = NULL;
*paramsp = params;
*nparamp = nparam;
+
+ return comma;
}
/*
@@ -2436,6 +2588,13 @@ static enum cond_state if_condition(Token * tline, enum preproc_token ct)
break;
case PP_IFDEF:
+ case PP_IFDEFALIAS:
+ {
+ bool alias = cond == PP_IFDEFALIAS;
+ SMacro *smac;
+ Context *ctx;
+ const char *mname;
+
j = false; /* have we matched yet? */
while (tline) {
tline = skip_white(tline);
@@ -2445,11 +2604,18 @@ static enum cond_state if_condition(Token * tline, enum preproc_token ct)
dname);
goto fail;
}
- if (smacro_defined(NULL, tok_text(tline), 0, NULL, true, false))
+
+ mname = tok_text(tline);
+ ctx = get_ctx(mname, &mname);
+ if (smacro_defined(ctx, mname, -1, &smac, true, alias) && smac
+ && smac->alias == alias) {
j = true;
+ break;
+ }
tline = tline->next;
}
break;
+ }
case PP_IFENV:
tline = expand_smacro(tline);
@@ -2926,6 +3092,8 @@ static SMacro *define_smacro(const char *mname, bool casesense,
if (tmpl) {
defining_alias = tmpl->alias;
nparam = tmpl->nparam;
+ if (nparam && !defining_alias)
+ mark_smac_params(expansion, tmpl, 0);
}
while (1) {
@@ -2947,7 +3115,7 @@ static SMacro *define_smacro(const char *mname, bool casesense,
* some others didn't. What is the right thing to do here?
*/
goto fail;
- } else if (!smac->alias || !do_aliases || defining_alias) {
+ } else if (!smac->alias || ppopt.noaliases || defining_alias) {
/*
* We're redefining, so we have to take over an
* existing SMacro structure. This means freeing
@@ -3016,14 +3184,14 @@ static void undef_smacro(const char *mname, bool undefalias)
while ((s = *sp) != NULL) {
if (!mstrcmp(s->name, mname, s->casesense)) {
if (s->alias && !undefalias) {
- if (!do_aliases)
- continue;
- if (s->in_progress) {
- nasm_nonfatal("macro alias loop");
- } else {
- s->in_progress = true;
- undef_smacro(tok_text(s->expansion), false);
- s->in_progress = false;
+ if (!ppopt.noaliases) {
+ if (s->in_progress) {
+ nasm_nonfatal("macro alias loop");
+ } else {
+ s->in_progress = true;
+ undef_smacro(tok_text(s->expansion), false);
+ s->in_progress = false;
+ }
}
} else {
if (list_option('d'))
@@ -3031,10 +3199,10 @@ static void undef_smacro(const char *mname, bool undefalias)
ctx, s);
*sp = s->next;
free_smacro(s);
+ continue;
}
- } else {
- sp = &s->next;
}
+ sp = &s->next;
}
}
}
@@ -3057,7 +3225,7 @@ static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
#endif
def->name = dup_text(tline);
def->plus = false;
- def->nolist = false;
+ def->nolist = 0;
def->nparam_min = 0;
def->nparam_max = 0;
@@ -3089,16 +3257,26 @@ static bool parse_mmacro_spec(Token *tline, MMacro *def, const char *directive)
tline->next->len == 7 &&
!nasm_stricmp(tline->next->text.a, ".nolist")) {
tline = tline->next;
- def->nolist = !list_option('f') || istk->nolist;
+ if (!list_option('f'))
+ def->nolist |= NL_LIST|NL_LINE;
}
/*
* Handle default parameters.
*/
+ def->ndefs = 0;
if (tline && tline->next) {
+ Token **comma;
def->dlist = tline->next;
tline->next = NULL;
- count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
+ comma = count_mmac_params(def->dlist, &def->ndefs, &def->defaults);
+ if (!ppopt.sane_empty_expansion && comma) {
+ *comma = NULL;
+ def->ndefs--;
+ nasm_warn(WARN_MACRO_PARAMS_LEGACY,
+ "dropping trailing empty default parameter in defintion of multi-line macro `%s'",
+ def->name);
+ }
} else {
def->dlist = NULL;
def->defaults = NULL;
@@ -3138,13 +3316,23 @@ static int parse_size(const char *str) {
*/
static void do_pragma_preproc(Token *tline)
{
+ const char *txt;
+
/* Skip to the real stuff */
tline = tline->next;
tline = skip_white(tline);
- if (!tline)
+
+ if (!tok_type(tline, TOK_ID))
return;
- (void)tline; /* Nothing else to do at present */
+ txt = tok_text(tline);
+ if (!nasm_stricmp(txt, "sane_empty_expansion")) {
+ tline = skip_white(tline->next);
+ ppopt.sane_empty_expansion =
+ pp_get_boolean_option(tline, ppopt.sane_empty_expansion);
+ } else {
+ /* Unknown pragma, ignore for now */
+ }
}
static bool is_macro_id(const Token *t)
@@ -3228,9 +3416,12 @@ static bool mmacro_cleanup(MMacro *m, bool emitting)
}
/*
- * End conditions of various loop types; also function as loop type identifiers.
- * Note that for loop operations, *unlike macro expansions*, these are also called
- * before the first time the loop body is emitted.
+ * End conditions of various loop types; also function as loop type
+ * identifiers. Note that for loop operations, *unlike macro
+ * expansions*, these are also called before the first time the loop
+ * body is emitted.
+ *
+ * Return true if the loop should be executed again.
*/
static bool loop_end_rep(MMacro *m, bool emitting)
{
@@ -3239,7 +3430,55 @@ static bool loop_end_rep(MMacro *m, bool emitting)
static bool loop_end_while(MMacro *m, bool emitting)
{
- return emitting && if_condition(dup_tlist(m->iline, NULL), m->loop.cond) == COND_IF_TRUE;
+ return emitting &&
+ if_condition(dup_tlist(m->iline, NULL), m->loop.cond) == COND_IF_TRUE;
+}
+
+/*
+ * Mark parameter tokens in an smacro definition. If the type argument
+ * is 0, create smac param tokens, otherwise use the type specified;
+ * normally this is used for TOK_XDEF_PARAM, which is used to protect
+ * parameter tokens during expansion during %xdefine.
+ *
+ * tmpl may not be NULL here.
+ */
+static void mark_smac_params(Token *tline, const SMacro *tmpl,
+ enum pp_token_type type)
+{
+ const struct smac_param *params = tmpl->params;
+ int nparam = tmpl->nparam;
+ Token *t;
+ int i;
+
+ list_for_each(t, tline) {
+ if (t->type != TOK_ID && t->type != TOK_XDEF_PARAM)
+ continue;
+
+ for (i = 0; i < nparam; i++) {
+ if (tok_text_match(t, &params[i].name))
+ t->type = type ? type : tok_smac_param(i);
+ }
+ }
+}
+
+/**
+ * %clear selected macro sets either globally or in contexts
+ */
+static void do_clear(enum clear_what what, bool context)
+{
+ if (context) {
+ if (what & CLEAR_ALLDEFINE) {
+ Context *ctx;
+ list_for_each(ctx, cstk)
+ clear_smacro_table(&ctx->localmac, what);
+ }
+ /* Nothing else can be context-local */
+ } else {
+ if (what & CLEAR_ALLDEFINE)
+ clear_smacro_table(&smacros, what);
+ if (what & CLEAR_MMACRO)
+ free_mmacro_table(&mmacros);
+ }
}
/**
@@ -3258,11 +3497,10 @@ static bool loop_end_while(MMacro *m, bool emitting)
static int do_directive(Token *tline, Token **output)
{
- enum preproc_token i;
+ enum preproc_token op;
int j;
bool err;
- int nparam;
- bool nolist;
+ enum nolist_flags nolist;
bool casesense;
int k, m;
int offset;
@@ -3295,12 +3533,62 @@ static int do_directive(Token *tline, Token **output)
if (dname[1] == '%')
return NO_DIRECTIVE_FOUND;
- i = pp_token_hash(dname);
+ op = pp_token_hash(dname);
casesense = true;
- if (PP_HAS_CASE(i) & PP_INSENSITIVE(i)) {
+ if (PP_HAS_CASE(op) & PP_INSENSITIVE(op)) {
casesense = false;
- i--;
+ op--;
+ }
+
+ /*
+ * %line directives are always processed immediately and
+ * unconditionally, as they are intended to reflect position
+ * in externally preprocessed sources.
+ */
+ if (op == PP_LINE) {
+ /*
+ * Syntax is `%line nnn[+mmm] [filename]'
+ */
+ if (pp_noline || istk->mstk.mstk)
+ goto done;
+
+ tline = tline->next;
+ tline = skip_white(tline);
+ if (!tok_type(tline, TOK_NUMBER)) {
+ nasm_nonfatal("`%s' expects line number", dname);
+ goto done;
+ }
+ k = readnum(tok_text(tline), &err);
+ m = 1;
+ tline = tline->next;
+ if (tok_is(tline, '+') || tok_is(tline, '-')) {
+ bool minus = tok_is(tline, '-');
+ tline = tline->next;
+ if (!tok_type(tline, TOK_NUMBER)) {
+ nasm_nonfatal("`%s' expects line increment", dname);
+ goto done;
+ }
+ m = readnum(tok_text(tline), &err);
+ if (minus)
+ m = -m;
+ tline = tline->next;
+ }
+ tline = skip_white(tline);
+ if (tline) {
+ if (tline->type == TOK_STRING) {
+ src_set_fname(unquote_token(tline));
+ } else {
+ char *fname = detoken(tline, false);
+ src_set_fname(fname);
+ nasm_free(fname);
+ }
+ }
+ src_set_linnum(k);
+
+ istk->where = src_where();
+ istk->lineinc = m;
+ goto done;
}
/*
@@ -3310,7 +3598,7 @@ static int do_directive(Token *tline, Token **output)
* directives.
*/
if (((istk->conds && !emitting(istk->conds->state)) || istk->popping) &&
- !is_condition(i)) {
+ !is_condition(op)) {
return NO_DIRECTIVE_FOUND;
}
@@ -3322,10 +3610,10 @@ static int do_directive(Token *tline, Token **output)
*/
if (defining) {
struct nested_def *nd;
- enum preproc_token ii = i;
+ enum preproc_token opx = op;
enum preproc_token closer;
- switch (i) {
+ switch (op) {
case PP_MACRO:
case PP_RMACRO:
closer = PP_ENDMACRO;
@@ -3359,7 +3647,7 @@ static int do_directive(Token *tline, Token **output)
goto is_closer;
case PP_ENDM:
- ii = PP_ENDMACRO;
+ opx = PP_ENDMACRO;
goto is_closer;
case PP_ENDMACRO:
@@ -3367,7 +3655,7 @@ static int do_directive(Token *tline, Token **output)
is_closer:
nd = nested_def;
- if (!nd || nd->closer != ii)
+ if (!nd || nd->closer != opx)
break;
nested_def = nd->next;
@@ -3379,7 +3667,7 @@ static int do_directive(Token *tline, Token **output)
}
}
- switch (i) {
+ switch (op) {
default:
nasm_nonfatal("unknown preprocessor directive `%s'", dname);
return NO_DIRECTIVE_FOUND; /* didn't get it */
@@ -3590,11 +3878,56 @@ static int do_directive(Token *tline, Token **output)
break;
case PP_CLEAR:
- if (tline->next)
+ {
+ bool context = false;
+
+ t = tline->next = expand_smacro(tline->next);
+ t = skip_white(t);
+ if (!t) {
+ /* Emulate legacy behavior */
+ do_clear(CLEAR_DEFINE|CLEAR_MMACRO, false);
+ } else {
+ while ((t = skip_white(t)) && t->type == TOK_ID) {
+ const char *txt = tok_text(t);
+ if (!nasm_stricmp(txt, "all")) {
+ do_clear(CLEAR_ALL, context);
+ } else if (!nasm_stricmp(txt, "define") ||
+ !nasm_stricmp(txt, "def") ||
+ !nasm_stricmp(txt, "smacro")) {
+ do_clear(CLEAR_DEFINE, context);
+ } else if (!nasm_stricmp(txt, "defalias") ||
+ !nasm_stricmp(txt, "alias") ||
+ !nasm_stricmp(txt, "salias")) {
+ do_clear(CLEAR_DEFALIAS, context);
+ } else if (!nasm_stricmp(txt, "alldef") ||
+ !nasm_stricmp(txt, "alldefine")) {
+ do_clear(CLEAR_ALLDEFINE, context);
+ } else if (!nasm_stricmp(txt, "macro") ||
+ !nasm_stricmp(txt, "mmacro")) {
+ do_clear(CLEAR_MMACRO, context);
+ } else if (!nasm_stricmp(txt, "context") ||
+ !nasm_stricmp(txt, "ctx")) {
+ context = true;
+ } else if (!nasm_stricmp(txt, "global")) {
+ context = false;
+ } else if (!nasm_stricmp(txt, "nothing") ||
+ !nasm_stricmp(txt, "none") ||
+ !nasm_stricmp(txt, "ignore") ||
+ !nasm_stricmp(txt, "-") ||
+ !nasm_stricmp(txt, "--")) {
+ /* Do nothing */
+ } else {
+ nasm_nonfatal("invalid option to %s: %s", dname, txt);
+ t = NULL;
+ }
+ }
+ }
+
+ t = skip_white(t);
+ if (t)
nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored", dname);
- free_macros();
- init_macros();
break;
+ }
case PP_DEPEND:
t = tline->next = expand_smacro(tline->next);
@@ -3611,6 +3944,7 @@ static int do_directive(Token *tline, Token **output)
goto done;
case PP_INCLUDE:
+ case PP_REQUIRE:
t = tline->next = expand_smacro(tline->next);
t = skip_white(t);
@@ -3626,16 +3960,19 @@ static int do_directive(Token *tline, Token **output)
inc->next = istk;
found_path = NULL;
inc->fp = inc_fopen(p, deplist, &found_path,
- (pp_mode == PP_DEPS)
- ? INC_OPTIONAL : INC_NEEDED, NF_TEXT);
+ (pp_mode == PP_DEPS) ? INC_OPTIONAL :
+ (op == PP_REQUIRE) ? INC_REQUIRED :
+ INC_NEEDED, NF_TEXT);
if (!inc->fp) {
- /* -MG given but file not found */
+ /* -MG given but file not found, or repeated %require */
nasm_free(inc);
} else {
- inc->fname = src_set_fname(found_path ? found_path : p);
- inc->lineno = src_set_linnum(0);
+ inc->where = src_where();
inc->lineinc = 1;
inc->nolist = istk->nolist;
+ inc->noline = istk->noline;
+ if (!inc->noline)
+ src_set(0, found_path ? found_path : p);
istk = inc;
lfmt->uplevel(LIST_INCLUDE, 0);
}
@@ -3661,9 +3998,10 @@ static int do_directive(Token *tline, Token **output)
stdmacpos = pkg->macros;
nasm_new(inc);
inc->next = istk;
- inc->fname = src_set_fname(NULL);
- inc->lineno = src_set_linnum(0);
- inc->nolist = !list_option('b') || istk->nolist;
+ inc->nolist = istk->nolist + !list_option('b');
+ inc->noline = istk->noline;
+ if (!inc->noline)
+ src_set(0, NULL);
istk = inc;
lfmt->uplevel(LIST_INCLUDE, 0);
}
@@ -3677,19 +4015,18 @@ static int do_directive(Token *tline, Token **output)
tline = expand_id(tline);
if (tline) {
if (!tok_type(tline, TOK_ID)) {
- nasm_nonfatal("`%s' expects a context identifier",
- pp_directives[i]);
+ nasm_nonfatal("`%s' expects a context identifier", dname);
goto done;
}
if (tline->next)
nasm_warn(WARN_OTHER, "trailing garbage after `%s' ignored",
- pp_directives[i]);
+ dname);
p = tok_text(tline);
} else {
p = NULL; /* Anonymous */
}
- if (i == PP_PUSH) {
+ if (op == PP_PUSH) {
nasm_new(ctx);
ctx->depth = cstk ? cstk->depth + 1 : 1;
ctx->next = cstk;
@@ -3699,9 +4036,8 @@ static int do_directive(Token *tline, Token **output)
} else {
/* %pop or %repl */
if (!cstk) {
- nasm_nonfatal("`%s': context stack is empty",
- pp_directives[i]);
- } else if (i == PP_POP) {
+ nasm_nonfatal("`%s': context stack is empty", dname);
+ } else if (op == PP_POP) {
if (p && (!cstk->name || nasm_stricmp(p, cstk->name)))
nasm_nonfatal("`%s' in wrong context: %s, "
"expected %s",
@@ -3709,7 +4045,7 @@ static int do_directive(Token *tline, Token **output)
else
ctx_pop();
} else {
- /* i == PP_REPL */
+ /* op == PP_REPL */
nasm_free((char *)cstk->name);
cstk->name = p ? nasm_strdup(p) : NULL;
p = NULL;
@@ -3755,7 +4091,7 @@ issue_error:
if (istk->conds && !emitting(istk->conds->state))
j = COND_NEVER;
else {
- j = if_condition(tline->next, i);
+ j = if_condition(tline->next, op);
tline->next = NULL; /* it got freed */
}
cond = nasm_malloc(sizeof(Cond));
@@ -3794,7 +4130,7 @@ issue_error:
* the normal invocation of expand_mmac_params().
* Therefore, we have to do it explicitly here.
*/
- j = if_condition(expand_mmac_params(tline->next), i);
+ j = if_condition(expand_mmac_params(tline->next), op);
tline->next = NULL; /* it got freed */
istk->conds->state = j;
break;
@@ -3844,19 +4180,23 @@ issue_error:
case PP_RMACRO:
case PP_MACRO:
+ {
+ MMacro *def;
+
nasm_assert(!defining);
- nasm_new(defining);
- defining->casesense = casesense;
- defining->cleanup = mmacro_cleanup;
- defining->dstk.mmac = defining;
- if (i == PP_RMACRO)
- defining->max_depth = nasm_limit[LIMIT_MACRO_LEVELS];
- if (!parse_mmacro_spec(tline, defining, dname)) {
- nasm_free(defining);
+ nasm_new(def);
+ def->casesense = casesense;
+ def->cleanup = mmacro_cleanup;
+ def->dstk.mmac = defining;
+ if (op == PP_RMACRO)
+ def->max_depth = nasm_limit[LIMIT_MACRO_LEVELS];
+ if (!parse_mmacro_spec(tline, def, dname)) {
+ nasm_free(def);
goto done;
}
- src_get(&defining->xline, &defining->fname);
+ defining = def;
+ defining->where = istk->where;
mmac = (MMacro *) hash_findix(&mmacros, defining->name);
while (mmac) {
@@ -3872,6 +4212,7 @@ issue_error:
mmac = mmac->next;
}
break;
+ }
case PP_ENDM:
case PP_ENDMACRO:
@@ -3998,13 +4339,13 @@ issue_error:
nasm_new(defining);
defining->nolist = nolist;
defining->cleanup = loop_end_rep;
- defining->loop.cond = i;
+ defining->loop.cond = op;
defining->iline = dup_tlist(tline, NULL);
defining->cleanup = loop_end_while;
defining->mstk = istk->mstk;
defining->dstk.mstk = tmp_defining;
defining->dstk.mmac = tmp_defining ? tmp_defining->dstk.mmac : NULL;
- src_get(&defining->xline, &defining->fname);
+ defining->where = src_where();
break;
}
@@ -4019,11 +4360,12 @@ issue_error:
{
MMacro *tmp_defining;
- nolist = false;
+ nolist = 0;
tline = skip_white(tline->next);
if (tok_type(tline, TOK_ID) && tline->len == 7 &&
!nasm_memicmp(tline->text.a, ".nolist", 7)) {
- nolist = !list_option('f') || istk->nolist;
+ if (!list_option('f'))
+ nolist |= NL_LIST; /* ... but update line numbers */
tline = skip_white(tline->next);
}
@@ -4071,7 +4413,7 @@ issue_error:
defining->mstk = istk->mstk;
defining->dstk.mstk = tmp_defining;
defining->dstk.mmac = tmp_defining ? tmp_defining->dstk.mmac : NULL;
- src_get(&defining->xline, &defining->fname);
+ defining->where = istk->where;
break;
}
@@ -4098,7 +4440,6 @@ issue_error:
*/
defining = d->dstk.mstk;
- lfmt->uplevel(d->nolist ? LIST_MACRO_NOLIST : LIST_MACRO, 0);
/* Are we going to execute at least one iteration? */
if (d->cleanup(d, true)) {
@@ -4107,8 +4448,14 @@ issue_error:
l->next = istk->expansion;
l->finishes = d;
l->first = NULL;
+ l->where = src_where();
istk->expansion = l;
istk->mstk.mstk = d;
+
+ /* Loops are never NL_LINE */
+ istk->nolist += !!(d->nolist & NL_LIST);
+ if (istk->nolist)
+ lfmt->uplevel(LIST_MACRO, 0);
} else {
/* Zero iterations, just discard everything */
free_mmacro(d);
@@ -4143,6 +4490,7 @@ issue_error:
{
SMacro tmpl;
Token **lastp;
+ int nparam;
if (!(mname = get_id(&tline, dname)))
goto done;
@@ -4153,7 +4501,7 @@ issue_error:
tline = *lastp;
*lastp = NULL;
- if (unlikely(i == PP_DEFALIAS)) {
+ if (unlikely(op == PP_DEFALIAS)) {
macro_start = tline;
if (!is_macro_id(macro_start)) {
nasm_nonfatal("`%s' expects a macro identifier to alias",
@@ -4171,30 +4519,14 @@ issue_error:
free_tlist(tt);
tmpl.alias = true;
} else {
- /* Expand the macro definition now for %xdefine and %ixdefine */
- if (i == PP_XDEFINE)
+ if (op == PP_XDEFINE) {
+ /* Protect macro parameter tokens */
+ if (nparam)
+ mark_smac_params(tline, &tmpl, TOK_XDEF_PARAM);
tline = expand_smacro(tline);
-
- /* Reverse expansion list and mark parameter tokens */
- macro_start = NULL;
- t = tline;
- while (t) {
- if (t->type == TOK_ID) {
- const char *ttext = tok_text(t);
- size_t tlen = t->len;
- for (i = 0; i < nparam; i++) {
- if (tmpl.params[i].name.len == t->len &&
- !memcmp(ttext, tok_text(&tmpl.params[i].name), tlen)) {
- t->type = tok_smac_param(i);
- break;
- }
- }
- }
- tt = t->next;
- t->next = macro_start;
- macro_start = t;
- t = tt;
}
+ /* NB: Does this still make sense? */
+ macro_start = reverse_tokens(tline);
}
/*
@@ -4216,7 +4548,7 @@ issue_error:
if (tline->next)
nasm_warn(WARN_OTHER, "trailing garbage after macro name ignored");
- undef_smacro(mname, i == PP_UNDEFALIAS);
+ undef_smacro(mname, op == PP_UNDEFALIAS);
break;
case PP_DEFSTR:
@@ -4369,18 +4701,19 @@ issue_error:
}
}
- q = qbuf = nasm_malloc(len);
+ q = qbuf = nasm_malloc(len+1);
list_for_each(t, tline) {
if (t->type == TOK_INTERNAL_STRING)
q = mempcpy(q, tok_text(t), t->len);
}
+ *q = '\0';
/*
* We now have a macro name, an implicit parameter count of
* zero, and a numeric token to use as an expansion. Create
* and store an SMacro.
*/
- macro_start = make_tok_qstr(NULL, qbuf);
+ macro_start = make_tok_qstr_len(NULL, qbuf, len);
nasm_free(qbuf);
define_smacro(mname, casesense, macro_start, NULL);
free_tlist(tline);
@@ -4457,7 +4790,7 @@ issue_error:
txt = (start < 0) ? "" : tok_text(t) + start;
len = count;
- macro_start = make_tok_qstr(NULL, txt);
+ macro_start = make_tok_qstr_len(NULL, txt, len);
/*
* We now have a macro name, an implicit parameter count of
@@ -4507,42 +4840,11 @@ issue_error:
case PP_ALIASES:
tline = tline->next;
tline = expand_smacro(tline);
- do_aliases = pp_get_boolean_option(tline, do_aliases);
+ ppopt.noaliases = !pp_get_boolean_option(tline, !ppopt.noaliases);
break;
case PP_LINE:
- /*
- * Syntax is `%line nnn[+mmm] [filename]'
- */
- if (unlikely(pp_noline))
- goto done;
-
- tline = tline->next;
- tline = skip_white(tline);
- if (!tok_type(tline, TOK_NUMBER)) {
- nasm_nonfatal("`%s' expects line number", dname);
- goto done;
- }
- k = readnum(tok_text(tline), &err);
- m = 1;
- tline = tline->next;
- if (tok_is(tline, '+')) {
- tline = tline->next;
- if (!tok_type(tline, TOK_NUMBER)) {
- nasm_nonfatal("`%s' expects line increment", dname);
- goto done;
- }
- m = readnum(tok_text(tline), &err);
- tline = tline->next;
- }
- tline = skip_white(tline);
- src_set_linnum(k);
- istk->lineinc = m;
- if (tline) {
- char *fname = detoken(tline, false);
- src_set_fname(fname);
- nasm_free(fname);
- }
+ nasm_panic("`%s' directive not preprocessed early", dname);
break;
}
@@ -4627,9 +4929,8 @@ static bool paste_tokens(Token **head, const struct tokseq_match *m,
if (!handle_explicit)
break;
- /* Left pasting token is start of line */
+ /* Left pasting token is start of line, just drop %+ */
if (!prev_nonspace) {
- nasm_nonfatal("No lvalue found on pasting");
tok = delete_Token(tok);
break;
}
@@ -4642,28 +4943,25 @@ static bool paste_tokens(Token **head, const struct tokseq_match *m,
/* Delete leading whitespace */
next = zap_white(t->next);
- /* Delete the %+ token itself */
- nasm_assert(next == tok);
- next = delete_Token(next);
-
- /* Delete trailing whitespace */
- next = zap_white(next);
+ /*
+ * Delete the %+ token itself, followed by any whitespace.
+ * In a sequence of %+ ... %+ ... %+ pasting sequences where
+ * some expansions in the middle have ended up empty,
+ * we can end up having multiple %+ tokens in a row;
+ * just drop whem in that case.
+ */
+ while (next) {
+ if (next->type == TOK_PASTE || next->type == TOK_WHITESPACE)
+ next = delete_Token(next);
+ else
+ break;
+ }
/*
- * No ending token, this might happen in two
- * cases
- *
- * 1) There indeed no right token at all
- * 2) There is a bare "%define ID" statement,
- * and @ID does expand to whitespace.
- *
- * So technically we need to do a grammar analysis
- * in another stage of parsing, but for now lets don't
- * change the behaviour people used to. Simply allow
- * whitespace after paste token.
+ * Nothing after? Just leave the existing token.
*/
if (!next) {
- *prev_nonspace = tok = NULL; /* End of line */
+ t->next = tok = NULL; /* End of line */
break;
}
@@ -4763,17 +5061,15 @@ static int mmac_rotate(const MMacro *mac, unsigned int n)
/*
* expands to a list of tokens from %{x:y}
*/
-static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
+static void expand_mmac_params_range(MMacro *mac, Token *tline, Token ***tail)
{
- Token *t = tline, **tt, *tm, *head;
- char *pos;
- int fst, lst, j, i;
-
- pos = strchr(tok_text(tline), ':');
- nasm_assert(pos);
+ Token *t;
+ const char *arg = tok_text(tline) + 1;
+ int fst, lst, incr, n;
+ int parsed;
- lst = atoi(pos + 1);
- fst = atoi(tok_text(tline) + 1);
+ parsed = sscanf(arg, "%d:%d", &fst, &lst);
+ nasm_assert(parsed == 2);
/*
* only macros params are accounted so
@@ -4791,56 +5087,28 @@ static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
fst = fst < 0 ? fst + (int)mac->nparam + 1: fst;
lst = lst < 0 ? lst + (int)mac->nparam + 1: lst;
- /* count from zero */
- fst--, lst--;
-
/*
- * It will be at least one token. Note we
- * need to scan params until separator, otherwise
- * only first token will be passed.
+ * It will be at least one parameter, as we can loop
+ * in either direction.
*/
- j = (fst + mac->rotate) % mac->nparam;
- tm = mac->params[j+1];
- if (!tm)
- goto err;
- head = dup_Token(NULL, tm);
- tt = &head->next, tm = tm->next;
- while (tok_isnt(tm, ',')) {
- t = dup_Token(NULL, tm);
- *tt = t, tt = &t->next, tm = tm->next;
- }
+ incr = (fst < lst) ? 1 : -1;
- if (fst < lst) {
- for (i = fst + 1; i <= lst; i++) {
- t = make_tok_char(NULL, ',');
- *tt = t, tt = &t->next;
- j = (i + mac->rotate) % mac->nparam;
- tm = mac->params[j+1];
- while (tok_isnt(tm, ',')) {
- t = dup_Token(NULL, tm);
- *tt = t, tt = &t->next, tm = tm->next;
- }
- }
- } else {
- for (i = fst - 1; i >= lst; i--) {
- t = make_tok_char(NULL, ',');
- *tt = t, tt = &t->next;
- j = (i + mac->rotate) % mac->nparam;
- tm = mac->params[j+1];
- while (!tok_isnt(tm, ',')) {
- t = dup_Token(NULL, tm);
- *tt = t, tt = &t->next, tm = tm->next;
- }
- }
+ while (true) {
+ n = mmac_rotate(mac, fst);
+ dup_tlistn(mac->params[n], mac->paramlen[n], tail);
+ if (fst == lst)
+ break;
+ t = make_tok_char(NULL, ',');
+ **tail = t;
+ *tail = &t->next;
+ fst += incr;
}
- *last = tt;
- return head;
+ return;
err:
- nasm_nonfatal("`%%{%s}': macro parameters out of range",
- tok_text(tline) + 1);
- return NULL;
+ nasm_nonfatal("`%%{%s}': macro parameters out of range", arg);
+ return;
}
/*
@@ -4859,6 +5127,7 @@ static Token *expand_mmac_params(Token * tline)
while (tline) {
bool change;
+ bool err_not_mac = false;
Token *t = tline;
const char *text = tok_text(t);
int type = t->type;
@@ -4868,9 +5137,15 @@ static Token *expand_mmac_params(Token * tline)
switch (type) {
case TOK_LOCAL_SYMBOL:
+ change = true;
+
+ if (!mac) {
+ err_not_mac = true;
+ break;
+ }
+
type = TOK_ID;
text = nasm_asprintf("..@%"PRIu64".%s", mac->unique, text+2);
- change = true;
break;
case TOK_MMACRO_PARAM:
{
@@ -4879,22 +5154,14 @@ static Token *expand_mmac_params(Token * tline)
change = true;
if (!mac) {
- nasm_nonfatal("`%s': not in a macro call", text);
- text = NULL;
+ err_not_mac = true;
break;
}
if (strchr(text, ':')) {
- /*
- * seems we have a parameters range here
- */
- Token *head, **last;
- head = expand_mmac_params_range(mac, t, &last);
- if (head) {
- *tail = head;
- *last = tline;
- text = NULL;
- }
+ /* It is a range */
+ expand_mmac_params_range(mac, t, &tail);
+ text = NULL;
break;
}
@@ -4936,13 +5203,11 @@ static Token *expand_mmac_params(Token * tline)
unsigned long n;
char *ep;
- text = NULL;
-
n = strtoul(tok_text(t) + 2, &ep, 10);
if (unlikely(*ep))
goto invalid;
- if (n && n < mac->nparam) {
+ if (n && n <= mac->nparam) {
n = mmac_rotate(mac, n);
tt = mac->params[n];
}
@@ -5015,6 +5280,12 @@ static Token *expand_mmac_params(Token * tline)
break;
}
+ if (err_not_mac) {
+ nasm_nonfatal("`%s': not in a macro call", text);
+ text = NULL;
+ change = true;
+ }
+
if (change) {
if (!text) {
delete_Token(t);
@@ -5110,7 +5381,7 @@ static SMacro *expand_one_smacro(Token ***tpp)
* checking for parameters if necessary.
*/
list_for_each(m, head) {
- if (unlikely(m->alias && !do_aliases))
+ if (unlikely(m->alias && ppopt.noaliases))
continue;
if (!mstrcmp(m->name, mname, m->casesense))
break;
@@ -5171,7 +5442,7 @@ static SMacro *expand_one_smacro(Token ***tpp)
switch (t->text.a[0]) {
case ',':
- if (!brackets)
+ if (!brackets && paren == 1)
nparam++;
break;
@@ -5212,7 +5483,7 @@ static SMacro *expand_one_smacro(Token ***tpp)
*! warns about \i{single-line macros} being invoked
*! with the wrong number of parameters.
*/
- nasm_warn(WARN_MACRO_PARAMS_SINGLE,
+ nasm_warn(WARN_MACRO_PARAMS_SINGLE|ERR_HOLD,
"single-line macro `%s' exists, "
"but not taking %d parameter%s",
mname, nparam, (nparam == 1) ? "" : "s");
@@ -5286,7 +5557,7 @@ static SMacro *expand_one_smacro(Token ***tpp)
switch (ch) {
case ',':
- if (!brackets && !(flags & SPARM_GREEDY)) {
+ if (!brackets && paren == 1 && !(flags & SPARM_GREEDY)) {
i++;
nasm_assert(i < nparam);
phead = pep = &params[i];
@@ -5482,8 +5753,10 @@ static SMacro *expand_one_smacro(Token ***tpp)
Token *endt = tline;
tline = t;
- while (!cond_comma && t && t != endt)
+ while (!cond_comma && t && t != endt) {
cond_comma = t->type != TOK_WHITESPACE;
+ t = t->next;
+ }
}
if (tnext) {
@@ -5495,7 +5768,7 @@ static SMacro *expand_one_smacro(Token ***tpp)
}
**tpp = tline;
- for (t = tline; t != tafter; t = t->next)
+ for (t = tline; t && t != tafter; t = t->next)
*tpp = &t->next;
m->in_progress = false;
@@ -5538,6 +5811,7 @@ static Token *expand_smacro_noreset(Token *org_tline)
{
Token *tline;
bool expanded;
+ errhold errhold; /* Hold warning/errors during expansion */
if (!org_tline)
return NULL; /* Empty input */
@@ -5557,6 +5831,7 @@ static Token *expand_smacro_noreset(Token *org_tline)
* look up the macro "MACROTAIL", which we don't want.
*/
expanded = true;
+
while (true) {
static const struct tokseq_match tmatch[] = {
{
@@ -5573,10 +5848,17 @@ static Token *expand_smacro_noreset(Token *org_tline)
};
Token **tail = &tline;
+ /*
+ * We hold warnings/errors until we are done this this loop. It is
+ * possible for nuisance warnings to appear that disappear on later
+ * passes.
+ */
+ errhold = nasm_error_hold_push();
+
while (*tail) /* main token loop */
expanded |= !!expand_one_smacro(&tail);
- if (!expanded)
+ if (!expanded)
break; /* Done! */
/*
@@ -5589,8 +5871,10 @@ static Token *expand_smacro_noreset(Token *org_tline)
if (!paste_tokens(&tline, tmatch, ARRAY_SIZE(tmatch), true))
break; /* Done again! */
+ nasm_error_hold_pop(errhold, false);
expanded = false;
}
+ nasm_error_hold_pop(errhold, true);
if (!tline) {
/*
@@ -5665,6 +5949,92 @@ static Token *expand_id(Token * tline)
}
/*
+ * This is called from find_mmacro_in_list() after finding a suitable macro.
+ */
+static MMacro *use_mmacro(MMacro *m, int *nparamp, Token ***paramsp)
+{
+ int nparam = *nparamp;
+ Token **params = *paramsp;
+
+ /*
+ * This one is right. Just check if cycle removal
+ * prohibits us using it before we actually celebrate...
+ */
+ if (m->in_progress > m->max_depth) {
+ if (m->max_depth > 0) {
+ nasm_warn(WARN_OTHER, "reached maximum recursion depth of %i",
+ m->max_depth);
+ }
+ nasm_free(params);
+ *nparamp = 0;
+ *paramsp = NULL;
+ return NULL;
+ }
+
+ /*
+ * It's right, and we can use it. Add its default
+ * parameters to the end of our list if necessary.
+ */
+ if (m->defaults && nparam < m->nparam_min + m->ndefs) {
+ int newnparam = m->nparam_min + m->ndefs;
+ params = nasm_realloc(params, sizeof(*params) * (newnparam+2));
+ memcpy(&params[nparam+1], &m->defaults[nparam+1-m->nparam_min],
+ (newnparam - nparam) * sizeof(*params));
+ nparam = newnparam;
+ }
+ /*
+ * If we've gone over the maximum parameter count (and
+ * we're in Plus mode), ignore parameters beyond
+ * nparam_max.
+ */
+ if (m->plus && nparam > m->nparam_max)
+ nparam = m->nparam_max;
+
+ /*
+ * If nparam was adjusted above, make sure the list is still
+ * NULL-terminated.
+ */
+ params[nparam+1] = NULL;
+
+ /* Done! */
+ *paramsp = params;
+ *nparamp = nparam;
+ return m;
+}
+
+/*
+ * Search a macro list and try to find a match. If matching, call
+ * use_mmacro() to set up the macro call. m points to the list of
+ * search, which is_mmacro() sets to the first *possible* match.
+ */
+static MMacro *
+find_mmacro_in_list(MMacro *m, const char *finding,
+ int *nparamp, Token ***paramsp)
+{
+ int nparam = *nparamp;
+
+ while (m) {
+ if (m->nparam_min <= nparam
+ && (m->plus || nparam <= m->nparam_max)) {
+ /*
+ * This one matches, use it.
+ */
+ return use_mmacro(m, nparamp, paramsp);
+ }
+
+ /*
+ * Otherwise search for the next one with a name match.
+ */
+ list_for_each(m, m->next) {
+ if (!mstrcmp(m->name, finding, m->casesense))
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+/*
* Determine whether the given line constitutes a multi-line macro
* call, and return the MMacro structure called if so. Doesn't have
* to check for an initial label - that's taken care of in
@@ -5672,12 +6042,16 @@ static Token *expand_id(Token * tline)
* to be called with tline->type == TOK_ID, so the putative macro
* name is easy to find.
*/
-static MMacro *is_mmacro(Token * tline, int *nparamp, Token ***params_array)
+static MMacro *is_mmacro(Token * tline, int *nparamp, Token ***paramsp)
{
- MMacro *head, *m;
- Token **params;
- int nparam;
+ MMacro *head, *m, *found;
+ Token **params, **comma;
+ int raw_nparam, nparam;
const char *finding = tok_text(tline);
+ bool empty_args = !tline->next;
+
+ *nparamp = 0;
+ *paramsp = NULL;
head = (MMacro *) hash_findix(&mmacros, finding);
@@ -5703,64 +6077,128 @@ static MMacro *is_mmacro(Token * tline, int *nparamp, Token ***params_array)
* OK, we have a potential macro. Count and demarcate the
* parameters.
*/
- count_mmac_params(tline->next, &nparam, &params);
+ comma = count_mmac_params(tline->next, nparamp, paramsp);
+ raw_nparam = *nparamp;
/*
- * So we know how many parameters we've got. Find the MMacro
- * structure that handles this number.
+ * Search for an exact match. This cannot come *before* the m
+ * found in the list search before, so we can start there.
+ *
+ * If found is NULL and *paramsp has been cleared, then we
+ * encountered an error for which we have already issued a
+ * diagnostic, so we should not proceed.
*/
- while (m) {
- if (m->nparam_min <= nparam
- && (m->plus || nparam <= m->nparam_max)) {
- /*
- * This one is right. Just check if cycle removal
- * prohibits us using it before we actually celebrate...
- */
- if (m->in_progress > m->max_depth) {
- if (m->max_depth > 0) {
- nasm_warn(WARN_OTHER, "reached maximum recursion depth of %i",
- m->max_depth);
- }
- nasm_free(params);
- return NULL;
- }
- /*
- * It's right, and we can use it. Add its default
- * parameters to the end of our list if necessary.
- */
- if (m->defaults && nparam < m->nparam_min + m->ndefs) {
- int newnparam = m->nparam_min + m->ndefs;
- params = nasm_realloc(params, sizeof(*params) * (newnparam+2));
- memcpy(&params[nparam+1], &m->defaults[nparam+1-m->nparam_min],
- (newnparam - nparam) * sizeof(*params));
- nparam = newnparam;
+ found = find_mmacro_in_list(m, finding, nparamp, paramsp);
+ if (!*paramsp)
+ return NULL;
+
+ nparam = *nparamp;
+ params = *paramsp;
+
+ /*
+ * Special weirdness: in NASM < 2.15, an expansion of
+ * *only* whitespace, as can happen during macro expansion under
+ * certain circumstances, is counted as zero arguments for the
+ * purpose of %0, but one argument for the purpose of macro
+ * matching! In particular, this affects:
+ *
+ * foobar %1
+ *
+ * ... with %1 being empty; this would call the one-argument
+ * version of "foobar" with an empty argument, equivalent to
+ *
+ * foobar {%1}
+ *
+ * ... except that %0 would be set to 0 inside foobar, even if
+ * foobar is declared with "%macro foobar 1" or equivalent!
+ *
+ * The proper way to do that is to define "%macro foobar 0-1".
+ *
+ * To be compatible without doing something too stupid, try to
+ * match a zero-argument macro first, but if that fails, try
+ * for a one-argument macro with the above behavior.
+ *
+ * Furthermore, NASM < 2.15 will match stripping a tailing empty
+ * argument, but in that case %0 *does* reflect that this argument
+ * have been stripped; this is handled in count_mmac_params().
+ *
+ * To disable these insane legacy behaviors, use:
+ *
+ * %pragma preproc sane_empty_expansion yes
+ *
+ *!macro-params-legacy [on] improperly calling multi-line macro for legacy support
+ *! warns about \i{multi-line macros} being invoked
+ *! with the wrong number of parameters, but for bug-compatibility
+ *! with NASM versions older than 2.15, NASM tried to fix up the
+ *! parameters to match the legacy behavior and call the macro anyway.
+ *! This can happen in certain cases where there are empty arguments
+ *! without braces, sometimes as a result of macro expansion.
+ *!-
+ *! The legacy behavior is quite strange and highly context-dependent,
+ *! and can be disabled with:
+ *!-
+ *! \c %pragma preproc sane_empty_expansion true
+ *!-
+ *! It is highly recommended to use this option in new code.
+ */
+ if (!ppopt.sane_empty_expansion) {
+ if (!found) {
+ if (raw_nparam == 0 && !empty_args) {
+ /*
+ * A single all-whitespace parameter as the only thing?
+ * Look for a one-argument macro, but don't adjust
+ * *nparamp.
+ */
+ int bogus_nparam = 1;
+ params[2] = NULL;
+ found = find_mmacro_in_list(m, finding, &bogus_nparam, paramsp);
+ } else if (raw_nparam > 1 && comma) {
+ Token *comma_tail = *comma;
+
+ /*
+ * Drop the terminal argument and try again.
+ * If we fail, we need to restore the comma to
+ * preserve tlist.
+ */
+ *comma = NULL;
+ *nparamp = raw_nparam - 1;
+ found = find_mmacro_in_list(m, finding, nparamp, paramsp);
+ if (found)
+ free_tlist(comma_tail);
+ else
+ *comma = comma_tail;
}
- /*
- * If we've gone over the maximum parameter count (and
- * we're in Plus mode), ignore parameters beyond
- * nparam_max.
- */
- if (m->plus && nparam > m->nparam_max)
- nparam = m->nparam_max;
- /*
- * If nparam was adjusted above, make sure the list is still
- * NULL-terminated.
- */
- params[nparam+1] = NULL;
+ if (!*paramsp)
+ return NULL;
+ } else if (comma) {
+ free_tlist(*comma);
+ *comma = NULL;
+ if (raw_nparam > found->nparam_min &&
+ raw_nparam <= found->nparam_min + found->ndefs) {
+ /* Replace empty argument with default parameter */
+ params[raw_nparam] =
+ found->defaults[raw_nparam - found->nparam_min];
+ } else if (raw_nparam > found->nparam_max && found->plus) {
+ /* Just drop the comma, don't adjust argument count */
+ } else {
+ /* Drop argument. This may cause nparam < nparam_min. */
+ params[raw_nparam] = NULL;
+ *nparamp = nparam = raw_nparam - 1;
+ }
+ }
- /* Done! */
- *params_array = params;
- *nparamp = nparam;
- return m;
+ if (found) {
+ if (raw_nparam < found->nparam_min ||
+ (raw_nparam > found->nparam_max && !found->plus)) {
+ nasm_warn(WARN_MACRO_PARAMS_LEGACY,
+ "improperly calling multi-line macro `%s' with %d parameters",
+ found->name, raw_nparam);
+ } else if (comma) {
+ nasm_warn(WARN_MACRO_PARAMS_LEGACY,
+ "dropping trailing empty parameter in call to multi-line macro `%s'", found->name);
+ }
}
- /*
- * This one wasn't right: look for the next one with the
- * same name.
- */
- list_for_each(m, m->next)
- if (!mstrcmp(m->name, tok_text(tline), m->casesense))
- break;
}
/*
@@ -5772,10 +6210,13 @@ static MMacro *is_mmacro(Token * tline, int *nparamp, Token ***params_array)
*! with the wrong number of parameters. See \k{mlmacover} for an
*! example of why you might want to disable this warning.
*/
+ if (found)
+ return found;
+
nasm_warn(WARN_MACRO_PARAMS_MULTI,
"multi-line macro `%s' exists, but not taking %d parameter%s",
- tok_text(tline), nparam, (nparam == 1) ? "" : "s");
- nasm_free(params);
+ finding, nparam, (nparam == 1) ? "" : "s");
+ nasm_free(*paramsp);
return NULL;
}
@@ -5937,13 +6378,10 @@ static int expand_mmacro(Token * tline)
/*
* Fix up the parameters: this involves stripping leading and
- * trailing whitespace, then stripping braces if they are
- * present.
+ * trailing whitespace and stripping braces if they are present.
*/
nasm_newn(paramlen, nparam+1);
- nasm_assert(params[nparam+1] == NULL);
-
for (i = 1; (t = params[i]); i++) {
bool braced = false;
int brace = 0;
@@ -6013,6 +6451,7 @@ static int expand_mmacro(Token * tline)
nasm_new(ll);
ll->next = istk->expansion;
ll->finishes = m;
+ ll->where = istk->where;
istk->expansion = ll;
/*
@@ -6032,7 +6471,6 @@ static int expand_mmacro(Token * tline)
m->rotate = 0;
m->paramlen = paramlen;
m->unique = unique++;
- m->lineno = 0;
m->condcnt = 0;
m->mstk = istk->mstk;
@@ -6043,6 +6481,7 @@ static int expand_mmacro(Token * tline)
ll->next = istk->expansion;
istk->expansion = ll;
ll->first = dup_tlist(l->first, NULL);
+ ll->where = l->where;
}
/*
@@ -6067,6 +6506,7 @@ static int expand_mmacro(Token * tline)
ll->next = istk->expansion;
istk->expansion = ll;
ll->first = startline;
+ ll->where = istk->where;
if (!dont_prepend) {
while (label->next)
label = label->next;
@@ -6075,10 +6515,18 @@ static int expand_mmacro(Token * tline)
}
}
- lfmt->uplevel(m->nolist ? LIST_MACRO_NOLIST : LIST_MACRO, 0);
+ istk->nolist += !!(m->nolist & NL_LIST);
+ istk->noline += !!(m->nolist & NL_LINE);
- if (list_option('m') && !m->nolist)
- list_mmacro_call(m);
+ if (!istk->nolist) {
+ lfmt->uplevel(LIST_MACRO, 0);
+
+ if (list_option('m'))
+ list_mmacro_call(m);
+ }
+
+ if (!istk->noline)
+ src_macro_push(m, istk->where);
return 1;
}
@@ -6197,7 +6645,9 @@ pp_reset(const char *file, enum preproc_mode mode, struct strlist *dep_list)
unique = 0;
deplist = dep_list;
pp_mode = mode;
- do_aliases = true;
+
+ /* Reset options to default */
+ nasm_zero(ppopt);
if (!use_loaded)
use_loaded = nasm_malloc(use_package_count * sizeof(bool));
@@ -6206,10 +6656,13 @@ pp_reset(const char *file, enum preproc_mode mode, struct strlist *dep_list)
/* First set up the top level input file */
nasm_new(istk);
istk->fp = nasm_open_read(file, NF_TEXT);
+ if (!istk->fp) {
+ nasm_fatalf(ERR_NOFILE, "unable to open input file `%s'%s%s",
+ file, errno ? " " : "", errno ? strerror(errno) : "");
+ }
src_set(0, file);
+ istk->where = src_where();
istk->lineinc = 1;
- if (!istk->fp)
- nasm_fatalf(ERR_NOFILE, "unable to open input file `%s'", file);
strlist_add(deplist, file);
@@ -6219,7 +6672,8 @@ pp_reset(const char *file, enum preproc_mode mode, struct strlist *dep_list)
*/
nasm_new(inc);
inc->next = istk;
- inc->fname = src_set_fname(NULL);
+ src_set(0, NULL);
+ inc->where = src_where();
inc->nolist = !list_option('b');
istk = inc;
lfmt->uplevel(LIST_INCLUDE, 0);
@@ -6281,22 +6735,21 @@ static Token tok_pop; /* Dummy token placeholder */
static Token *pp_tokline(void)
{
+ struct Token *tline, *dtline;
+
while (true) {
Line *l = istk->expansion;
- Token *tline = NULL;
- Token *dtline;
/*
* Fetch a tokenized line, either from the macro-expansion
* buffer or from the input file.
*/
- tline = NULL;
while (l && l->finishes) {
MMacro *fm = l->finishes;
bool again;
/*
- * Check whether a `%rep' was started and not ended
+ * Check whether a loop was started and not ended
* within this macro expansion. This can happen and
* should be detected. It's a fatal error because
* I'm too confused to work out how to recover
@@ -6324,38 +6777,43 @@ static Token *pp_tokline(void)
Line *ll;
nasm_new(ll);
- ll->next = istk->expansion;
+ ll->next = istk->expansion;
ll->first = dup_tlist(l->first, NULL);
+ ll->where = l->where;
istk->expansion = ll;
}
break;
} else {
MMacro *m = istk->mstk.mstk;
+ nasm_assert(m == fm);
+
if (istk->popping == fm) /* Resume normal expansion */
istk->popping = NULL;
- /*
- * FIXME: investigate the relationship at this point between
- * istk->mstk.mstk and fm
- */
istk->mstk = m->mstk;
+ fm->in_progress = false;
-#if 0
- /*
- * FIXME It is incorrect to always free_mmacro here.
- * It leads to usage-after-free.
- *
- * https://bugzilla.nasm.us/show_bug.cgi?id=3392414
- */
- if (!m->name)
- free_mmacro(m);
-#endif
+ if (fm->nolist & NL_LIST) {
+ istk->nolist--;
+ } else if (!istk->nolist) {
+ lfmt->downlevel(LIST_MACRO);
+ }
+
+ if (fm->nolist & NL_LINE) {
+ istk->noline--;
+ } else if (!istk->noline) {
+ if (fm == src_macro_current())
+ src_macro_pop();
+ src_update(l->where);
+ }
+
+ istk->where = l->where;
+ istk->expansion = l->next;
+ nasm_free(l);
+
+ return &tok_pop;
}
- istk->expansion = l->next;
- nasm_free(l);
- lfmt->downlevel(LIST_MACRO);
- return &tok_pop;
}
do { /* until we get a line we can use */
@@ -6363,27 +6821,20 @@ static Token *pp_tokline(void)
if (istk->expansion) { /* from a macro expansion */
Line *l = istk->expansion;
- int32_t lineno;
-
- if (istk->mstk.mstk) {
- istk->mstk.mstk->lineno++;
- if (istk->mstk.mstk->fname)
- lineno = istk->mstk.mstk->lineno +
- istk->mstk.mstk->xline;
- else
- lineno = 0; /* Defined at init time or builtin */
- } else {
- lineno = src_get_linnum();
- }
- tline = l->first;
istk->expansion = l->next;
+ istk->where = l->where;
+ tline = l->first;
nasm_free(l);
- line = detoken(tline, false);
- if (!istk->nolist)
- lfmt->line(LIST_MACRO, lineno, line);
- nasm_free(line);
+ if (!istk->noline)
+ src_update(istk->where);
+
+ if (!istk->nolist) {
+ line = detoken(tline, false);
+ lfmt->line(LIST_MACRO, istk->where.lineno, line);
+ nasm_free(line);
+ }
} else if ((line = read_line())) {
line = prepreproc(line);
tline = tokenize(line);
@@ -6393,17 +6844,23 @@ static Token *pp_tokline(void)
* The current file has ended; work down the istk
*/
Include *i = istk;
+ Include *is;
+
if (i->fp)
fclose(i->fp);
if (i->conds) {
- /* nasm_error can't be conditionally suppressed */
+ /* nasm_fatal can't be conditionally suppressed */
nasm_fatal("expected `%%endif' before end of file");
}
- /* only set line and file name if there's a next node */
- if (i->next)
- src_set(i->lineno, i->fname);
+
+ list_for_each(is, i->next) {
+ if (is->fp) {
+ lfmt->downlevel(LIST_INCLUDE);
+ src_update(is->where);
+ break;
+ }
+ }
istk = i->next;
- lfmt->downlevel(LIST_INCLUDE);
nasm_free(i);
return &tok_pop;
}
@@ -6437,11 +6894,13 @@ static Token *pp_tokline(void)
* shove the tokenized line on to the macro definition.
*/
MMacro *mmac = defining->dstk.mmac;
+ Line *l;
- Line *l = nasm_malloc(sizeof(Line));
+ nasm_new(l);
l->next = defining->expansion;
l->first = tline;
l->finishes = NULL;
+ l->where = istk->where;
defining->expansion = l;
/*
@@ -6667,12 +7126,15 @@ static Token *make_tok_num(Token *next, int64_t val)
}
/* Create a quoted string token */
-static Token *make_tok_qstr(Token *next, const char *str)
+static Token *make_tok_qstr_len(Token *next, const char *str, size_t len)
{
- size_t len = strlen(str);
char *p = nasm_quote(str, &len);
return new_Token_free(next, TOK_STRING, p, len);
}
+static Token *make_tok_qstr(Token *next, const char *str)
+{
+ return make_tok_qstr_len(next, str, strlen(str));
+}
/* Create a single-character operator token */
static Token *make_tok_char(Token *next, char op)
@@ -6682,31 +7144,21 @@ static Token *make_tok_char(Token *next, char op)
return t;
}
-static void pp_list_one_macro(MMacro *m, errflags severity)
-{
- if (!m)
- return;
-
- /* We need to print the mstk.mmac list in reverse order */
- pp_list_one_macro(m->mstk.mmac, severity);
-
- if (m->name && !m->nolist) {
- src_set(m->xline + m->lineno, m->fname);
- nasm_error(severity, "... from macro `%s' defined", m->name);
- }
-}
-
+/*
+ * Descent the macro hierarchy and display the expansion after
+ * encountering an error message.
+ */
static void pp_error_list_macros(errflags severity)
{
- struct src_location saved;
+ const MMacro *m;
severity |= ERR_PP_LISTMACRO | ERR_NO_SEVERITY | ERR_HERE;
- saved = src_where();
- if (istk)
- pp_list_one_macro(istk->mstk.mmac, severity);
+ while ((m = src_error_down())) {
+ nasm_error(severity, "... from macro `%s' defined", m->name);
+ }
- src_update(saved);
+ src_error_reset();
}
const struct preproc_ops nasmpp = {
diff --git a/asm/srcfile.c b/asm/srcfile.c
index 0f35c5af..b44c021c 100644
--- a/asm/srcfile.c
+++ b/asm/srcfile.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2018 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2020 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -32,7 +32,14 @@
* ----------------------------------------------------------------------- */
/*
- * srcfile.c - keep track of the current position in the input stream
+ * srcfile.c - keep track of the current position in the input stream.
+ *
+ * This is used for error messages, listing, and debug information. In
+ * both cases we also want to understand where inside a non-nolist
+ * macro we may be.
+ *
+ * This hierarchy is a stack that is kept as a doubly-linked list, as
+ * we want to traverse it in either top-down order or bottom-up.
*/
#include "compiler.h"
@@ -42,7 +49,9 @@
#include "hashtbl.h"
#include "srcfile.h"
-struct src_location _src_here;
+struct src_location_stack _src_top;
+struct src_location_stack *_src_bottom = &_src_top;
+struct src_location_stack *_src_error = &_src_top;
static struct hash_table filename_hash;
@@ -75,8 +84,8 @@ const char *src_set_fname(const char *newname)
}
}
- oldname = _src_here.filename;
- _src_here.filename = newname;
+ oldname = _src_bottom->l.filename;
+ _src_bottom->l.filename = newname;
return oldname;
}
@@ -86,12 +95,24 @@ void src_set(int32_t line, const char *fname)
src_set_linnum(line);
}
-struct src_location src_update(struct src_location whence)
+void src_macro_push(const void *macro, struct src_location where)
+{
+ struct src_location_stack *sl;
+
+ nasm_new(sl);
+ sl->l = where;
+ sl->macro = macro;
+ sl->up = _src_bottom;
+ _src_bottom->down = sl;
+ _src_bottom = sl;
+}
+
+void src_macro_pop(void)
{
- struct src_location oldhere = _src_here;
+ struct src_location_stack *sl = _src_bottom;
- src_set_fname(whence.filename);
- src_set_linnum(whence.lineno);
+ _src_bottom = sl->up;
+ _src_bottom->down = NULL;
- return oldhere;
+ nasm_free(sl);
}
diff --git a/asm/srcfile.h b/asm/srcfile.h
index 3af6595e..a26e1e4f 100644
--- a/asm/srcfile.h
+++ b/asm/srcfile.h
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2016 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2020 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -43,25 +43,33 @@ struct src_location {
const char *filename;
int32_t lineno;
};
-extern struct src_location _src_here;
+struct src_location_stack {
+ struct src_location l;
+ struct src_location_stack *up, *down;
+ const void *macro;
+};
+extern struct src_location_stack _src_top;
+extern struct src_location_stack *_src_bottom;
+extern struct src_location_stack *_src_error;
void src_init(void);
void src_free(void);
const char *src_set_fname(const char *newname);
static inline const char *src_get_fname(void)
{
- return _src_here.filename;
+ return _src_bottom->l.filename;
}
static inline int32_t src_set_linnum(int32_t newline)
{
- int32_t oldline = _src_here.lineno;
- _src_here.lineno = newline;
+ int32_t oldline = _src_bottom->l.lineno;
+ _src_bottom->l.lineno = newline;
return oldline;
}
static inline int32_t src_get_linnum(void)
{
- return _src_here.lineno;
+ return _src_bottom->l.lineno;
}
+
/* Can be used when there is no need for the old information */
void src_set(int32_t line, const char *filename);
@@ -79,24 +87,79 @@ static inline int32_t src_get(int32_t *xline, const char **xname)
{
const char *xn = *xname;
int32_t xl = *xline;
+ int32_t line = _src_bottom->l.lineno;
- *xline = _src_here.lineno;
- *xname = _src_here.filename;
+ *xline = line;
+ *xname = _src_bottom->l.filename;
/* The return value is expected to be optimized out almost everywhere */
- if (!xn || xn != _src_here.filename)
+ if (!xn || xn != _src_bottom->l.filename)
return -2;
else
- return _src_here.lineno - xl;
+ return line - xl;
}
/*
- * Returns and sets/returns the current information as a structure.
+ * Returns the current information as a structure.
*/
static inline struct src_location src_where(void)
{
- return _src_here;
+ return _src_bottom->l;
+}
+
+/*
+ * Returns the top-level information as a structure. Use this for panic
+ * errors, since descent is not possible there.
+ */
+static inline struct src_location src_where_top(void)
+{
+ return _src_top.l;
+}
+
+/*
+ * Returns the appropriate level of the location stack to use for error
+ * messages. This is the same as the top level except during the descent
+ * through the macro hierarchy for elucidation;
+ */
+static inline struct src_location src_where_error(void)
+{
+ return _src_error->l;
+}
+static inline const void *src_error_down(void)
+{
+ if (_src_error->down) {
+ _src_error = _src_error->down;
+ return _src_error->macro;
+ } else {
+ return NULL;
+ }
+}
+static inline void src_error_reset(void)
+{
+ _src_error = &_src_top;
+}
+
+/*
+ * Sets the current information. The filename member of the structure
+ * *must* have been previously returned by src_get(), src_where(), or
+ * src_get_fname() and therefore be present in the hash.
+ */
+static inline struct src_location src_update(struct src_location whence)
+{
+ struct src_location old = _src_bottom->l;
+ _src_bottom->l = whence;
+ return old;
+}
+
+/*
+ * Push/pop macro expansion level. "macroname" must remain constant at
+ * least until the same macro expansion level is popped.
+ */
+void src_macro_push(const void *macroname, struct src_location where);
+static inline const void *src_macro_current(void)
+{
+ return _src_bottom->macro;
}
-struct src_location src_update(struct src_location);
+void src_macro_pop(void);
#endif /* ASM_SRCFILE_H */
diff --git a/asm/stdscan.c b/asm/stdscan.c
index 4491430d..cbc0fc77 100644
--- a/asm/stdscan.c
+++ b/asm/stdscan.c
@@ -128,6 +128,8 @@ int stdscan(void *private_data, struct tokenval *tv)
(void)private_data; /* Don't warn that this parameter is unused */
+ nasm_zero(*tv);
+
stdscan_bufptr = nasm_skip_spaces(stdscan_bufptr);
if (!*stdscan_bufptr)
return tv->t_type = TOKEN_EOS;
@@ -162,7 +164,7 @@ int stdscan(void *private_data, struct tokenval *tv)
*!ptr [on] non-NASM keyword used in other assemblers
*! warns about keywords used in other assemblers that might
*! indicate a mistake in the source code. Currently only the MASM
- *! \c{PTR} keyword is recognized.
+ *! \c{PTR} keyword is recognized. See also \k{pkg_masm}.
*/
nasm_warn(WARN_PTR, "`%s' is not a NASM keyword",
tv->t_charptr);
diff --git a/asm/tokens.dat b/asm/tokens.dat
index 81875f0e..ab37dcc1 100644
--- a/asm/tokens.dat
+++ b/asm/tokens.dat
@@ -42,6 +42,7 @@
# Tokens other than instructions and registers
#
+# The ? operator is a keyword, because ? is a legitimate symbol character
% TOKEN_QMARK, 0, 0, 0
?
@@ -88,9 +89,14 @@ short
strict
to
+# PTR is a legitimate symbol, but has an optional warning
% TOKEN_ID, 0, TFLAG_WARN, 0
ptr
+# DUP is a legitimate symbol, but also has context-specific use in extops
+% TOKEN_ID, 0, TFLAG_DUP, 0
+dup
+
% TOKEN_FLOAT, 0, 0, 0
__?infinity?__
__?nan?__
diff --git a/asm/tokhash.pl b/asm/tokhash.pl
index 9dbe77a2..9303157b 100755
--- a/asm/tokhash.pl
+++ b/asm/tokhash.pl
@@ -234,19 +234,19 @@ if ($output eq 'h') {
# Put a large value in unused slots. This makes it extremely unlikely
# that any combination that involves unused slot will pass the range test.
# This speeds up rejection of unrecognized tokens, i.e. identifiers.
- print "#define UNUSED (65535/3)\n";
+ print "#define UNUSED_HASH_ENTRY (65535/3)\n";
print " static const int16_t hash1[$n] = {\n";
for ($i = 0; $i < $n; $i++) {
my $h = ${$g}[$i*2+0];
- print " ", defined($h) ? $h : 'UNUSED', ",\n";
+ print " ", defined($h) ? $h : 'UNUSED_HASH_ENTRY', ",\n";
}
print " };\n";
print " static const int16_t hash2[$n] = {\n";
for ($i = 0; $i < $n; $i++) {
my $h = ${$g}[$i*2+1];
- print " ", defined($h) ? $h : 'UNUSED', ",\n";
+ print " ", defined($h) ? $h : 'UNUSED_HASH_ENTRY', ",\n";
}
print " };\n";
diff --git a/asm/warnings.pl b/asm/warnings.pl
index a609e132..8a79568a 100755
--- a/asm/warnings.pl
+++ b/asm/warnings.pl
@@ -253,7 +253,18 @@ if ($what eq 'c') {
} else {
my $docdef = $whatdef{$warn->{def}};
- @doc = @{$warn->{doc}};
+ my $newpara = 0;
+ foreach my $l (@{$warn->{doc}}) {
+ if ($l =~ /^\s*$/) {
+ $newpara = 1;
+ } else {
+ if ($newpara && $l !~ /^\\c\s+/) {
+ $l = '\> ' . $l;
+ }
+ $newpara = 0;
+ }
+ push(@doc, $l);
+ }
if (defined($docdef)) {
push(@doc, "\n", "\\> $docdef by default.\n");
}
diff --git a/config/unconfig.h b/config/unconfig.h
index 4b01eb6e..c7d900fc 100644
--- a/config/unconfig.h
+++ b/config/unconfig.h
@@ -60,6 +60,12 @@
/* Define to 1 if compiled with the `-Wc90-c99-compat' compiler flag */
/* #undef CFLAGS_WC90_C99_COMPAT */
+/* Define to 1 if compiled with the `-Wc99-compat' compiler flag */
+/* #undef CFLAGS_WC99_COMPAT */
+
+/* Define to 1 if compiled with the `-Wc99-extensions' compiler flag */
+/* #undef CFLAGS_WC99_EXTENSIONS */
+
/* Define to 1 if compiled with the `-Werror' compiler flag */
/* #undef CFLAGS_WERROR */
@@ -225,6 +231,10 @@
functions */
/* #undef HAVE_FUNC_ATTRIBUTE_SENTINEL */
+/* Define to 1 if your compiler supports __attribute__((unused)) on functions
+ */
+/* #undef HAVE_FUNC_ATTRIBUTE_UNUSED */
+
/* Define to 1 if your compiler supports __attribute__((alloc_size)) on
function pointers */
/* #undef HAVE_FUNC_PTR_ATTRIBUTE1_ALLOC_SIZE */
@@ -265,12 +275,19 @@
pointers */
/* #undef HAVE_FUNC_PTR_ATTRIBUTE_SENTINEL */
+/* Define to 1 if your compiler supports __attribute__((unused)) on function
+ pointers */
+/* #undef HAVE_FUNC_PTR_ATTRIBUTE_UNUSED */
+
/* Define to 1 if you have the `getgid' function. */
/* #undef HAVE_GETGID */
/* Define to 1 if you have the `getpagesize' function. */
/* #undef HAVE_GETPAGESIZE */
+/* Define to 1 if you have the `getrlimit' function. */
+/* #undef HAVE_GETRLIMIT */
+
/* Define to 1 if you have the `getuid' function. */
/* #undef HAVE_GETUID */
@@ -385,6 +402,9 @@
/* Define to 1 if you have the <sys/param.h> header file. */
/* #undef HAVE_SYS_PARAM_H */
+/* Define to 1 if you have the <sys/resource.h> header file. */
+/* #undef HAVE_SYS_RESOURCE_H */
+
/* Define to 1 if you have the <sys/stat.h> header file. */
/* #undef HAVE_SYS_STAT_H */
@@ -708,6 +728,22 @@
# endif
#endif
+#ifndef unused_func
+# ifdef HAVE_FUNC_ATTRIBUTE_UNUSED
+# define unused_func __attribute__((unused))
+# else
+# define unused_func
+# endif
+#endif
+
+#ifndef unused_func_ptr
+# ifdef HAVE_FUNC_PTR_ATTRIBUTE_UNUSED
+# define unused_func_ptr __attribute__((unused))
+# else
+# define unused_func_ptr
+# endif
+#endif
+
#ifndef never_null
# ifdef HAVE_FUNC_ATTRIBUTE_RETURNS_NONNULL
# define never_null __attribute__((returns_nonnull))
diff --git a/configure.ac b/configure.ac
index 600056da..d9d45837 100644
--- a/configure.ac
+++ b/configure.ac
@@ -15,16 +15,14 @@ dnl the best very slow and doesn't buy us a single thing at all.
WINELOADER=/dev/null
export WINELOADER
+dnl Get the canonical target system name
+AC_CANONICAL_HOST
+
dnl Checks for programs and enable necessary CC extensions
AC_USE_SYSTEM_EXTENSIONS
AC_SYS_LARGEFILE
AC_PROG_CC
AC_PROG_CC_STDC
-AC_PROG_LN_S
-AC_PROG_MAKE_SET
-AC_PROG_INSTALL
-
-pa_no_optimize=false
dnl If the user did not specify a CFLAGS default, change default
dnl to -O0 for debugging
@@ -32,6 +30,19 @@ PA_ARG_DISABLED([optimization],
[compile without optimization (-O0) to help debugging],
[pa_no_optimize=true])
+dnl LLVM doesn't error out on invalid -W options unless this option is
+dnl specified first. Enable this so this script can actually discover
+dnl which -W options are possible for this compiler.
+PA_ADD_CFLAGS([-Werror=unknown-warning-option])
+
+dnl Other programs
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AC_PROG_INSTALL
+AC_PROG_MKDIR_P
+
+pa_no_optimize=false
+
dnl Compile and link with dwarf debug
PA_ARG_ENABLED([gdb],
[disable optimization and compile with extra debug information for GDB debugger],
@@ -87,14 +98,56 @@ dnl Look for programs...
AC_CHECK_PROGS(NROFF, nroff, false)
AC_CHECK_PROGS(ASCIIDOC, asciidoc, false)
AC_CHECK_PROGS(XMLTO, xmlto, false)
+AC_CHECK_PROGS(XZ, xz, false)
dnl Check for progs needed for manpage generation
-AS_IF([test $ASCIIDOC = false],
- [AC_MSG_WARN([No asciidoc package found])]
+MANPAGES=manpages
+AS_IF([test x$ASCIIDOC = xfalse],
+ [AC_MSG_WARN([No asciidoc package found, cannot build man pages])
+ MANPAGES='']
)
-AS_IF([test $XMLTO = false],
- [AC_MSG_WARN([No xmlto package found])]
+AS_IF([test x"$XMLTO" = xfalse],
+ [AC_MSG_WARN([No xmlto package found, cannot build man pages])
+ MANPAGES='']
)
+AC_SUBST([MANPAGES])
+
+dnl Don't create .pdf.xz if there is no xz
+AS_IF([test x"$XZ" = xfalse],
+ [],
+ [XZFILES=xzfiles])
+AC_SUBST([XZFILES])
+
+dnl Can't create NSIS package if there is no makensis
+dnl ... but it only applies to a Windows target ...
+dnl Note: AC_CHECK_TOOLS is supposed to check for the "plain"
+dnl version of the program name, but it doesn't seem to.
+AC_ARG_WITH([nsis],
+[AS_HELP_STRING([[--with-nsis[=makensis]]],
+ [build an install .exe using NSIS on Windows hosts])],
+ [], [with_nsis=yes])
+AS_IF([test x"$MAKENSIS" = x], [],
+ [AS_IF([test x"$with_nsis" = xno], []
+ [with_nsis="$MAKENSIS"])])
+
+MAKENSIS=false
+
+AS_CASE([$host],
+ [*-win* | *-mingw*],
+ [AS_IF([test x"$with_nsis" = xno], [],
+ [NSIS=nsis
+ AS_IF([test x"$with_nsis" = xyes],
+ [AC_CHECK_TOOL(MAKENSIS_TOOL, makensis, false)
+ MAKENSIS="$MAKENSIS_TOOL"
+ AS_IF([test x"$MAKENSIS" = xfalse],
+ [AC_CHECK_PROGS(MAKENSIS_PLAIN, makensis, false)
+ MAKENSIS="$MAKENSIS_PLAIN"])
+ AS_IF([test x"$MAKENSIS" = xfalse],
+ [AC_MSG_WARN([no makensis found, cannot build installer])
+ NSIS=''])],
+ [MAKENSIS="$with_nsis"])])])
+AC_SUBST([MAKENSIS])
+AC_SUBST([NSIS])
dnl Check for host compiler tools
AC_CHECK_TOOL(AR, ar)
@@ -113,6 +166,7 @@ AC_CHECK_HEADERS(unistd.h)
AC_CHECK_HEADERS(sys/mman.h)
AC_CHECK_HEADERS(sys/types.h)
AC_CHECK_HEADERS(sys/stat.h)
+AC_CHECK_HEADERS(sys/resource.h)
dnl Checks for library functions.
AC_CHECK_FUNCS(strcasecmp stricmp)
@@ -126,6 +180,7 @@ AC_CHECK_FUNCS(mempcpy)
AC_CHECK_FUNCS(getuid)
AC_CHECK_FUNCS(getgid)
+AC_CHECK_FUNCS(getrlimit)
AC_CHECK_FUNCS(realpath)
AC_CHECK_FUNCS(canonicalize_file_name)
@@ -234,6 +289,7 @@ PA_FUNC_ATTRIBUTE(format, [printf,1,2], int, [const char *, ...], ["%d",1])
PA_FUNC_ATTRIBUTE(const)
PA_FUNC_ATTRIBUTE(pure)
PA_FUNC_ATTRIBUTE(cold,,,,,unlikely_func)
+PA_FUNC_ATTRIBUTE(unused)
PA_FUNC_ATTRIBUTE_ERROR
dnl
@@ -272,22 +328,25 @@ PA_ARG_ENABLED([sanitizer],
dnl
dnl Don't make symbols visible, there is no point and it just
-dnl makes the code slower.
+dnl makes the code slower. This mainly affects ELF.
dnl
PA_ADD_CFLAGS([-fvisibility=hidden])
-dnl If we have gcc, add appropriate code cleanliness options
+dnl
+dnl If we have gcc, add appropriate code cleanliness options. Do this
+dnl here at the end, because configure relies on being able to use
+dnl some very, very old C constructs.
+dnl
PA_ADD_CFLAGS([-Wall])
PA_ARG_DISABLED([pedantic],
[disable some extra paranoid compiler warnings],
[],
[PA_ADD_CFLAGS([-W])
PA_ADD_CFLAGS([-pedantic])
- PA_ADD_CFLAGS([-Wc90-c99-compat])])
-dnl LLVM doesn't error out on invalid -W options unless this option is
-dnl specified first. Enable this so this script can actually discover
-dnl which -W options are possible for this compiler.
-PA_ADD_CFLAGS([-Werror=unknown-warning-option])
+ PA_ADD_CFLAGS([-Wc90-c99-compat])
+ PA_ADD_CFLAGS([-Wc99-compat])
+ PA_ADD_CFLAGS([-Wc99-extensions])
+])
dnl Suppress format warning on Windows targets due to their <inttypes.h>
PA_ADD_CFLAGS([-Wpedantic-ms-format],[-Wno-pedantic-ms-format])
PA_ADD_CFLAGS([-Wlong-long],[-Wno-long-long])
@@ -299,6 +358,7 @@ dnl on compilers with gcc-like command line syntax we pass the -fwrapv
dnl option for exactly that reason.
PA_ADD_CFLAGS([-Wshift-negative-value],[-Wno-shift-negative-value])
+dnl Want to turn this on at some point...
dnl PA_ADD_CFLAGS([-Wwrite-strings])
PA_ARG_ENABLED([werror],
[compile with -Werror to error out on any warning],
@@ -327,5 +387,5 @@ dnl support ccache
dnl
PA_ARG_ENABLED([ccache], [compile with ccache], [CC="ccache $CC"], [])
-AC_OUTPUT_COMMANDS([mkdir -p config nasmlib nsis output stdlib x86 asm disasm rdoff macros common])
-AC_OUTPUT(Makefile doc/Makefile)
+AC_CONFIG_FILES([Makefile doc/Makefile])
+AC_OUTPUT
diff --git a/disasm/ndisasm.c b/disasm/ndisasm.c
index f3c23b00..01e0c557 100644
--- a/disasm/ndisasm.c
+++ b/disasm/ndisasm.c
@@ -280,8 +280,10 @@ int main(int argc, char **argv)
pname, filename, strerror(errno));
return 1;
}
- } else
+ } else {
+ nasm_set_binary_mode(stdin);
fp = stdin;
+ }
if (initskip > 0)
skip(initskip, fp);
diff --git a/doc/Makefile.in b/doc/Makefile.in
index ba44b44a..e92437a0 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -2,6 +2,8 @@
# UNIX Makefile for NASM documentation
#
+@SET_MAKE@
+
top_srcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
@@ -22,29 +24,39 @@ PERL = perl -I$(srcdir)
PDFOPT = @PDFOPT@
-MKDIR = mkdir
+MKDIR_P = @MKDIR_P@
RM_F = rm -f
RM_RF = rm -rf
CP_F = cp -f
-CP_UF = cp -ufv
+CP_UF = cp -uf
+
+# Optional tools
+XZ = @XZ@
+
+# Optional targets
+XZFILES = @XZFILES@
# Auxiliary files referenced by the HTML files
HTMLAUX = nasmdoc.css local.css nasmlogw.png
SRCS = nasmdoc.src inslist.src changes.src warnings.src version.src
-OUT = html nasmdoc.txt nasmdoc.pdf
+OUT = html nasmdoc.txt nasmdoc.pdf $(XZFILES)
+XZOUT = nasmdoc.pdf.xz
.SUFFIXES:
.SUFFIXES: .pfa .ph
+.PHONY: all xzfiles html clean spotless install
+
all: $(OUT)
+xzfiles: $(XZOUT)
+
inslist.src: inslist.pl ../x86/insns.dat
$(PERL) $(srcdir)/inslist.pl $(srcdir)/../x86/insns.dat
-.PHONY: html
html: $(HTMLAUX)
- $(MKDIR) -p html
+ $(MKDIR_P) html
for f in $(HTMLAUX); do $(CP_UF) "$(srcdir)/$$f" html/; done
$(MAKE) html/nasmdoc0.html
@@ -79,20 +91,37 @@ Fontmap: nasmdoc.ps
@: Generated by side effect
nasmdoc.pdf: nasmdoc.ps pspdf.pl fontpath
- $(PERL) $(srcdir)/pspdf.pl $(PDFOPT) nasmdoc.ps nasmdoc.pdf fontpath
+ $(PERL) $(srcdir)/pspdf.pl \
+ $(PDFOPT) $< $@ fontpath
+
+nasmdoc-raw.pdf: nasmdoc.ps pspdf.pl fontpath
+ $(PERL) $(srcdir)/pspdf.pl -nocompress \
+ $(PDFOPT) $< $@ fontpath
+
+nasmdoc.pdf.xz: nasmdoc-raw.pdf
+ $(RM_F) $@
+ $(XZ) -9e < $< > $@
clean:
-$(RM_F) *.rtf *.hpj *.texi *.gid *.ipf *.dip
-$(RM_F) *.aux *.cp *.fn *.ky *.pg *.log *.toc *.tp *.vr
-$(RM_F) inslist.src version.src fontpath Fontmap
- -$(RM_F) nasmdoc*.ps
+ -$(RM_F) nasmdoc*.ps nasmdoc-raw.pdf
spotless: clean
-$(RM_RF) html info
- -$(RM_F) *.hlp nasmdoc.txt *.inf *.pdf *.dvi
+ -$(RM_F) *.hlp nasmdoc.txt *.inf *.pdf *.pdf.xz *.dvi
install: all
- $(MKDIR) -p $(DESTDIR)$(htmldir)
+ $(MKDIR_P) $(DESTDIR)$(htmldir)
$(INSTALL_DATA) html/* $(DESTDIR)$(htmldir)
- $(MKDIR) -p $(DESTDIR)$(docdir)
+ $(MKDIR_P) $(DESTDIR)$(docdir)
$(INSTALL_DATA) nasmdoc.pdf nasmdoc.txt $(DESTDIR)$(docdir)
+
+#
+# Dummy rules that changes make behavior
+# (at end to avoid confusing non-GNU makes)
+#
+.SECONDARY:
+
+.DELETE_ON_ERROR:
diff --git a/doc/changes.src b/doc/changes.src
index eec64bca..e4bd3edf 100644
--- a/doc/changes.src
+++ b/doc/changes.src
@@ -7,12 +7,127 @@
The NASM 2 series supports x86-64, and is the production version of NASM
since 2007.
+\S{cl-2.15.02} Version 2.15.02
+
+\b Fix miscompilation when building with \c{clang}.
+
+\b Add \c{db-empty} warning class, see \k{opt-w}.
+
+\b Fix the dependencies in the MSVC NMAKE makefile (\c{Mkfiles/msvc.mak}).
+
+\b Some documentation improvements and cleanups.
+
+\b Fix the handling of macro parameter ranges (\c{%\{:\}}), including
+with brace-enclosed original arguments.
+
+\S{cl-2.15.01} Version 2.15.01
+
+\b Fix building the documentation from the release archive. For 2.15,
+the user has to do \c{make warnings} manually in the main directory in
+order to be able to build the documentation, which means Perl needs to
+be installed on the system.
+
+\b Add instructions for Intel Control Flow Enforcement Technology (CET).
+
\S{cl-2.15} Version 2.15
+\b The comparison and booleanizing operators can now be used in any
+expression context, not just \c{%if}. See \k{expr}.
+
+\b New operator \c{?} ... \c{:}. See \k{exptri}.
+
+\b Signed shift operators \c{<<<} and \c{>>>}. See \k{expshift}.
+
+\b The MASM \c{DUP} syntax for data definitions is now supported, in a
+somewhat enhanced form. See \k{db}.
+
+\b Warn for strange legacy behavior regarding empty arguments in
+multi-line macro expansion, but try to match legacy behavior in most
+cases. Legacy behavior can be disabled with the directive \c{%pragma
+preproc sane_empty_expansion}, see \k{mlmacro} and
+\k{pragma-preproc}.
+
+\b A much more sensible limit to expression evaluation depth. The
+previously defined limit would rarely trigger before NASM died with a
+stack overrun error on most systems. See \k{opt-limit}.
+
\b The state of warnings can now be saved and restored via the
\c{[WARNING PUSH]} and \c{[WARNING POP]} directives. See
\k{asmdir-warning}.
+\b The \c{sectalign on|off} switch does not affect an explicit directive. See
+\k{sectalign}.
+
+\b Added \c{configure} option to enable building with profiling
+(\c{--enable-profiling}).
+
+\b Attempt to support of long path names, up to 32767 of UTF-16
+characters, on Windows.
+
+\b Fixed 'mismatch in operand sizes' error in the \c{MOVDDUP},
+\c{CMPXCHG8B} and \c{CMPXCHG16B} instructions.
+
+\b Improved error messages in the string transformation routine.
+
+\b Removed obsolete \c{gnu-elf-extensions} warning about 8- and 16-bit
+relocation generation. See \k{elf16}
+
+\b Added group aliases for all prefixed warnings. See \k{opt-w}.
+
+\b Allowed building with MSVC versions older than 1700.
+
+\b Added implicitly sized versions of the \c{K...} instructions, which
+allows the \c{K...} instructions to be specified without a size suffix as
+long as the operands are sized.
+
+\b Added \c{-L} option for additional listing information. See \k{opt-L}.
+
+\b Added some warnings for obsolete instructions for a specified CPU.
+
+\b Deprecated \c{-hf} and \c{-y} options. Use \c{-h} instead.
+
+\b Made DWARF as the default debug format for ELF.
+
+\b Added \c{%pragma list} \e{options...} to set or clear listing options
+(see \c{opt-L}).
+
+\b Allowed immediate syntax for \c{LEA} instruction (ignore operand
+size completely).
+
+\b Added limited functionality MASM compatibility package. See
+\k{pkg_masm}.
+
+\b Add single-line macros aliases using \c{%defalias} or
+\c{%idefalias}. These behave like a kind of "symbolic links" for
+single-line macros. See \k{defalias} and \c{clear}.
+
+\b Added support for stringify, nostrip, evaluating, and greedy
+single-line macro arguments. See \k{define}.
+
+\b Unused single-line macro arguments no longer need to have a
+specified name. See \k{define}.
+
+\b Added conditional comma operator \c{%,}. See \k{cond-comma}.
+
+\b Changed private namespace from \c{__foo__} to \c{__?foo?__}, so a user
+namespace starting from underscore is now clean from symbols. For
+backwards compatibility, the previous names are defined as aliases; see
+\k{defalias}, \k{clear} and \k{stdmac}.
+
+\b Added support of ELF weak symbols and external references. See \k{elfglob}.
+
+\b Changed the behavior of the EXTERN keyword and introduced REQUIRED keyword.
+See \k{required}.
+
+\b Added \c{%ifusable} and \c{%ifusing} directives. See \k{macropkg}.
+
+\b Made various performance improvements and stability fixes in macro
+preprocessor engine.
+
+\b Improved NASM error handling and cleaned up error messages.
+
+\b Many, many bug fixes.
+
\S{cl-2.14.03} Version 2.14.03
\b Suppress nuisance "\c{label changed during code generation}" messages
@@ -93,7 +208,7 @@ renaming. See \k{opt-pfix}.
from the command line. See \k{mangling}.
\b Supported generic \c{%pragma} namespaces, \c{output} and \c{debug}. See
-\k{gen-namespace}.
+\k{pragma}.
\b Added the \c{--pragma} command line option to inject a \c{%pragma}
directive. See \k{opt-pragma}.
diff --git a/doc/genps.pl b/doc/genps.pl
index 7cbe23c0..72985cc7 100755
--- a/doc/genps.pl
+++ b/doc/genps.pl
@@ -1,7 +1,7 @@
#!/usr/bin/perl
## --------------------------------------------------------------------------
##
-## Copyright 1996-2017 The NASM Authors - All Rights Reserved
+## Copyright 1996-2020 The NASM Authors - All Rights Reserved
## See the file AUTHORS included with the NASM distribution for
## the specific copyright holders.
##
@@ -237,7 +237,7 @@ if (defined($fontmap)) {
'dieresis', undef, 'ring', 'cedilla', undef, 'hungarumlaut',
'ogonek', 'caron', 'space', 'exclam', 'quotedbl', 'numbersign',
'dollar', 'percent', 'ampersand', 'quoteright', 'parenleft',
- 'parenright', 'asterisk', 'plus', 'comma', 'minus', 'period',
+ 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period',
'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six',
'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal',
'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
@@ -254,7 +254,7 @@ if (defined($fontmap)) {
'scaron', 'guilsignlright', 'oe', undef, 'zcaron', 'Ydieresis',
'space', 'exclamdown', 'cent', 'sterling', 'currency', 'yen',
'brokenbar', 'section', 'dieresis', 'copyright', 'ordfeminine',
- 'guillemotleft', 'logicalnot', 'hyphen', 'registered', 'macron',
+ 'guillemotleft', 'logicalnot', 'minus', 'registered', 'macron',
'degree', 'plusminus', 'twosuperior', 'threesuperior', 'acute', 'mu',
'paragraph', 'periodcentered', 'cedilla', 'onesuperior',
'ordmasculine', 'guillemotright', 'onequarter', 'onehalf',
@@ -775,7 +775,7 @@ sub ps_break_lines($$) {
my $p;
# Code paragraph; each chunk is a line
foreach $p ( @data ) {
- push(@ls, [[$ptype,0,undef,\%BodyFont,0,0],[$p]]);
+ push(@ls, [[$ptype,0,undef,\%CodeFont,0,0],[$p]]);
}
$ls[0]->[0]->[1] |= 1; # First in para
$ls[-1]->[0]->[1] |= 2; # Last in para
diff --git a/doc/head.ps b/doc/head.ps
index 7fbb3a90..6109915d 100644
--- a/doc/head.ps
+++ b/doc/head.ps
@@ -246,10 +246,10 @@
/norm2 { lmarg exch moveto bfont showstream } def
/norm3 { lmarg exch moveto bfont showstream } def
-/code0 { lmarg exch moveto bfont showstream } def
-/code1 { lmarg exch moveto bfont showstream } def
-/code2 { lmarg exch moveto bfont showstream } def
-/code3 { lmarg exch moveto bfont showstream } def
+/code0 { lmarg exch moveto xfont showstream } def
+/code1 { lmarg exch moveto xfont showstream } def
+/code2 { lmarg exch moveto xfont showstream } def
+/code3 { lmarg exch moveto xfont showstream } def
/bull0 { bullmarg exch moveto bfont bwidth showstreamjust } def
/bull1 { dup lmarg exch moveto bullet bfont showstream
diff --git a/doc/nasmdoc.css b/doc/nasmdoc.css
index 6ad9e913..7926d2b4 100644
--- a/doc/nasmdoc.css
+++ b/doc/nasmdoc.css
@@ -18,6 +18,7 @@ span.subtitle {
}
code, pre {
font-family: "source code pro", "liberation mono", "monospace";
+ font-size: 80%;
}
pre, blockquote {
margin-left: 4em;
diff --git a/doc/nasmdoc.src b/doc/nasmdoc.src
index 69ccbc9f..eb49d1a8 100644
--- a/doc/nasmdoc.src
+++ b/doc/nasmdoc.src
@@ -1,6 +1,6 @@
\# --------------------------------------------------------------------------
\#
-\# Copyright 1996-2019 The NASM Authors - All Rights Reserved
+\# Copyright 1996-2020 The NASM Authors - All Rights Reserved
\# See the file AUTHORS included with the NASM distribution for
\# the specific copyright holders.
\#
@@ -53,6 +53,7 @@
\IR{-E} \c{-E} option
\IR{-F} \c{-F} option
\IR{-I} \c{-I} option
+\IR{-L} \c{-L} option
\IR{-M} \c{-M} option
\IR{-MD} \c{-MD} option
\IR{-MF} \c{-MF} option
@@ -81,13 +82,13 @@
\IR{-Werror} \c{-Werror} option
\IR{-Wno-error} \c{-Wno-error} option
\IR{-w} \c{-w} option
-\IR{-y} \c{-y} option
\IR{-Z} \c{-Z} option
\IR{!=} \c{!=} operator
\IR{$, here} \c{$}, Here token
\IR{$, prefix} \c{$}, prefix
\IR{$$} \c{$$} token
\IR{%} \c{%} operator
+\IR{%db} \c{%} prefix to \c{DB} lists
\IR{%%} \c{%%} operator
\IR{%+1} \c{%+1} and \c{%-1} syntax
\IA{%-1}{%+1}
@@ -100,14 +101,19 @@
\IR{//} \c{//} operator
\IR{<} \c{<} operator
\IR{<<} \c{<<} operator
+\IR{<<<} \c{<<<} operator
+\IR{<=>} \c{<=>} operator
\IR{<=} \c{<=} operator
\IR{<>} \c{<>} operator
+\IR{<=>} \c{<=>} operator
\IR{=} \c{=} operator
\IR{==} \c{==} operator
\IR{>} \c{>} operator
\IR{>=} \c{>=} operator
\IR{>>} \c{>>} operator
-\IR{?} \c{?} MASM syntax
+\IR{>>>} \c{>>>} operator
+\IR{?db} \c{?}, data syntax
+\IR{?op} \c{?}, operator
\IR{^} \c{^} operator
\IR{^^} \c{^^} operator
\IR{|} \c{|} operator
@@ -120,7 +126,13 @@
\IR{+ modifier} \c{+} modifier
\IR{- opsubtraction} \c{-} operator, binary
\IR{- opunary} \c{-} operator, unary
-\IR{! opunary} \c{!} operator, unary
+\IR{! opunary} \c{!} operator
+\IA{A16}{a16}
+\IA{A32}{a32}
+\IA{A64}{a64}
+\IA{O16}{o16}
+\IA{O32}{o32}
+\IA{O64}{o64}
\IR{alignment, in bin sections} alignment, in \c{bin} sections
\IR{alignment, in elf sections} alignment, in ELF sections
\IR{alignment, in win32 sections} alignment, in \c{win32} sections
@@ -146,10 +158,9 @@ variables
\IA{case-sensitive}{case sensitive}
\IA{case-insensitive}{case sensitive}
\IA{character constants}{character constant}
-\IR{codeview} CodeView debugging format
+\IR{codeview debugging format} CodeView debugging format
\IR{common object file format} Common Object File Format
-\IR{common variables, alignment in elf} common variables, alignment
-in ELF
+\IR{common variables, alignment in elf} common variables, alignment in ELF
\IR{common, elf extensions to} \c{COMMON}, ELF extensions to
\IR{common, obj extensions to} \c{COMMON}, \c{obj} extensions to
\IR{declaring structure} declaring structures
@@ -159,18 +170,17 @@ in ELF
\IR{dll symbols, exporting} DLL symbols, exporting
\IR{dll symbols, importing} DLL symbols, importing
\IR{dos} DOS
-\IR{dos archive} DOS archive
-\IR{dos source archive} DOS source archive
\IA{effective address}{effective addresses}
\IA{effective-address}{effective addresses}
\IR{elf} ELF
\IR{elf, 16-bit code} ELF, 16-bit code
\IR{elf, debug formats} ELF, debug formats
-\IR{elf shared libraries} ELF, shared libraries
+\IR{elf shared library} ELF, shared libraries
\IR{elf32} \c{elf32}
\IR{elf64} \c{elf64}
\IR{elfx32} \c{elfx32}
\IR{executable and linkable format} Executable and Linkable Format
+\IR{extern, elf extensions to} \c{EXTERN}, \c{elf} extensions to
\IR{extern, obj extensions to} \c{EXTERN}, \c{obj} extensions to
\IR{extern, rdf extensions to} \c{EXTERN}, \c{rdf} extensions to
\IR{floating-point, constants} floating-point, constants
@@ -178,8 +188,7 @@ in ELF
\IR{freebsd} FreeBSD
\IR{freelink} FreeLink
\IR{functions, c calling convention} functions, C calling convention
-\IR{functions, pascal calling convention} functions, Pascal calling
-convention
+\IR{functions, pascal calling convention} functions, \c{PASCAL} calling convention
\IR{global, aoutb extensions to} \c{GLOBAL}, \c{aoutb} extensions to
\IR{global, elf extensions to} \c{GLOBAL}, ELF extensions to
\IR{global, rdf extensions to} \c{GLOBAL}, \c{rdf} extensions to
@@ -191,9 +200,6 @@ convention
\IR{linux, elf} Linux, ELF
\IR{linux, a.out} Linux, \c{a.out}
\IR{linux, as86} Linux, \c{as86}
-\IR{logical and} logical AND
-\IR{logical or} logical OR
-\IR{logical xor} logical XOR
\IR{mach object file format} Mach, object file format
\IA{mach-o}{macho}
\IR{mach-o} Mach-O, object file format
@@ -201,29 +207,36 @@ convention
\IR{macho64} \c{macho64}
\IR{macos x} MacOS X
\IR{masm} MASM
+\IR{masmdb} MASM, \c{DB} syntax
\IA{memory reference}{memory references}
\IR{minix} Minix
\IA{misc directory}{misc subdirectory}
\IR{misc subdirectory} \c{misc} subdirectory
\IR{microsoft omf} Microsoft OMF
-\IR{mmx registers} MMX registers
-\IA{modr/m}{modr/m byte}
-\IR{modr/m byte} ModR/M byte
\IR{ms-dos} MS-DOS
\IR{ms-dos device drivers} MS-DOS device drivers
\IR{multipush} \c{multipush} macro
\IR{nan} NaN
\IR{nasm version} NASM version
+\IR{nasm version history} NASM version, history
+\IR{nasm version macros} NASM version, macros
+\IR{nasm version id} NASM version, ID macro
+\IR{nasm version string} NASM version, string macro
+\IR{arithmetic negation} negation, arithmetic
+\IR{bitwise negation} negation, bitwise
+\IR{boolean negation} negation, boolean
+\IR{boolean and} boolean, AND
+\IR{boolean or} boolean, OR
+\IR{boolean xor} boolean, XOR
\IR{netbsd} NetBSD
\IR{nsis} NSIS
\IR{nullsoft scriptable installer} Nullsoft Scriptable Installer
+\IA{.OBJ}{.obj}
\IR{omf} OMF
\IR{openbsd} OpenBSD
\IR{operating system} operating system
\IR{os/2} OS/2
-\IR{pascal calling convention}Pascal calling convention
-\IR{passes} passes, assembly
-\IR{perl} Perl
+\IR{pascal calling convention} Pascal calling convention
\IR{pic} PIC
\IR{pharlap} PharLap
\IR{plt} PLT
@@ -244,14 +257,16 @@ Object File Format
\IR{section alignment, in win32} section alignment, in \c{win32}
\IR{section, elf extensions to} \c{SECTION}, ELF extensions to
\IR{section, macho extensions to} \c{SECTION}, \c{macho} extensions to
-\IR{section, win32 extensions to} \c{SECTION}, \c{win32} extensions to
+\IR{section, windows extensions to} \c{SECTION}, Windows extensions to
\IR{segment alignment, in bin} segment alignment, in \c{bin}
\IR{segment alignment, in obj} segment alignment, in \c{obj}
-\IR{segment, obj extensions to} \c{SEGMENT}, ELF extensions to
+\IR{segment, obj extensions to} \c{SEGMENT}, \c{obj} extensions to
\IR{segment names, borland pascal} segment names, Borland Pascal
\IR{shift command} \c{shift} command
-\IA{sib}{sib byte}
-\IR{sib byte} SIB byte
+\IA{string constant}{string constants}
+\IR{string constants} string, constants
+\IR{string length} string, length
+\IR{string manipulation in macros} string, manipulation in macros
\IR{align, smart} \c{ALIGN}, smart
\IA{sectalign}{sectalign}
\IR{solaris x86} Solaris x86
@@ -262,7 +277,9 @@ Object File Format
\IR{thread local storage in elf} thread local storage, in ELF
\IR{thread local storage in mach-o} thread local storage, in \c{macho}
\IR{tlink} \c{TLINK}
+\IR{unconditionally importing symbols} importing symbols, unconditionally
\IR{underscore, in c symbols} underscore, in C symbols
+\IA{uninitialized storage}{storage, uninitialized}
\IR{unicode} Unicode
\IR{unix} Unix
\IR{utf-8} UTF-8
@@ -270,20 +287,16 @@ Object File Format
\IR{utf-32} UTF-32
\IA{sco unix}{unix, sco}
\IR{unix, sco} Unix, SCO
-\IA{unix source archive}{unix, source archive}
-\IR{unix, source archive} Unix, source archive
\IA{unix system v}{unix, system v}
\IR{unix, system v} Unix, System V
\IR{unixware} UnixWare
\IR{val} VAL
-\IR{version number of nasm} version number of NASM
+\IA{version number of nasm}{nasm, version}
\IR{visual c++} Visual C++
-\IR{www page} WWW page
\IR{win32} Win32
-\IR{win32} Win64
+\IR{win64} Win64
\IR{windows} Windows
-\IR{windows 95} Windows 95
-\IR{windows nt} Windows NT
+\IR{windows debugging formats} Windows, debugging formats
\# \IC{program entry point}{entry point, program}
\# \IC{program entry point}{start point, program}
\# \IC{MS-DOS device drivers}{device drivers, MS-DOS}
@@ -372,9 +385,6 @@ To get further usage instructions from NASM, try typing
The option \c{--help} is an alias for the \c{-h} option.
-The option \c{-hf} will also list the available output file formats,
-and what they are.
-
If you use Linux but aren't sure whether your system is \c{a.out}
or ELF, type
@@ -427,7 +437,7 @@ an intervening space. For example:
\c nasm -f bin driver.asm -odriver.sys
Note that this is a small o, and is different from a capital O , which
-is used to specify the number of optimisation passes required. See \k{opt-O}.
+is used to specify the number of optimization passes required. See \k{opt-O}.
\S{opt-f} The \i\c{-f} Option: Specifying the \i{Output File Format}
@@ -442,7 +452,7 @@ Like \c{-o}, the intervening space between \c{-f} and the output
file format is optional; so \c{-f elf} and \c{-felf} are both valid.
A complete list of the available output file formats can be given by
-issuing the command \i\c{nasm -hf}.
+issuing the command \i\c{nasm -h}.
\S{opt-l} The \i\c{-l} Option: Generating a \i{Listing File}
@@ -463,6 +473,44 @@ with \c{[list +]}, (the default, obviously). There is no "user
form" (without the brackets). This can be used to list only
sections of interest, avoiding excessively long listings.
+\S{opt-L} The \i\c{-L} Option: Additional or Modified Listing Info
+
+Use this option to specify listing output details.
+
+Supported options are:
+
+\b \c{-Lb} show builtin macro packages (standard and \c{%use})
+
+\b \c{-Ld} show byte and repeat counts in decimal, not hex
+
+\b \c{-Le} show the preprocessed input
+
+\b \c{-Lf} ignore \c{.nolist} and force listing output
+
+\b \c{-Lm} show multi-line macro calls with expanded parameters
+
+\b \c{-Lp} output a list file in every pass, in case of errors
+
+\b \c{-Ls} show all single-line macro definitions
+
+\b \c{-Lw} flush the output after every line (very slow!)
+
+\b \c{-L+} enable \e{all} listing options
+
+These options can be enabled or disabled at runtime using the
+\c{%pragma list options} directive:
+
+\c %pragma list options [+|-]flags...
+
+For example, to turn on the \c{d} and \c{m} flags but disable the
+\c{s} flag:
+
+\c %pragma list options +dm -s
+
+For forward compatility reasons, an undefined flag will be
+ignored. Thus, a new flag introduced in a newer version of NASM can be
+specified without breaking older versions. Listing flags will always
+be a single alphanumeric character and are case sensitive.
\S{opt-M} The \i\c{-M} Option: Generate \i{Makefile Dependencies}
@@ -551,8 +599,8 @@ to enable output. Versions 2.03.01 and later automatically enable \c{-g}
if \c{-F} is specified.
A complete list of the available debug file formats for an output
-format can be seen by issuing the command \c{nasm -f <format> -y}. Not
-all output formats currently support debugging output. See \k{opt-y}.
+format can be seen by issuing the command \c{nasm -h}. Not
+all output formats currently support debugging output.
This should not be confused with the \c{-f dbg} output format option,
see \k{dbgfmt}.
@@ -818,6 +866,10 @@ The current \i{warning classes} are:
\& warnings.src
+Since version 2.15, NASM has group aliases for all prefixed warnings,
+so they can be used to enable or disable all warnings in the group.
+For example, -w+float enables all warnings with names starting with float-*.
+
Since version 2.00, NASM has also supported the \c{gcc}-like syntax
\c{-Wwarning-class} and \c{-Wno-warning-class} instead of
\c{-w+warning-class} and \c{-w-warning-class}, respectively; both
@@ -845,19 +897,6 @@ You will need the version number if you report a bug.
For command-line compatibility with Yasm, the form \i\c{--v} is also
accepted for this option starting in NASM version 2.11.05.
-\S{opt-y} The \i\c{-y} Option: Display Available Debug Info Formats
-
-Typing \c{nasm -f <option> -y} will display a list of the available
-debug info formats for the given output format. The default format
-is indicated by an asterisk. For example:
-
-\c nasm -f elf -y
-
-\c valid debug formats for 'elf32' output format are
-\c ('*' denotes default):
-\c * stabs ELF32 (i386) stabs debug format for Linux
-\c dwarf elf32 (i386) dwarf debug format for Linux
-
\S{opt-pfix} The \i\c{--(g|l)prefix}, \i\c{--(g|l)postfix} Options.
@@ -884,7 +923,7 @@ Running this:
\c nasm -f macho --pragma "macho gprefix _"
-is equivalent to the example in \k{opt-pfix}.
+is equivalent to the example in \k{opt-pfix}. See \k{pragma}.
\S{opt-before} The \i\c{--before} Option
@@ -897,30 +936,44 @@ shown in \k{opt-pragma} is the same as running this:
\S{opt-limit} The \i\c{--limit-X} Option
-This option allows user to setup various maximum values for these:
+This option allows user to setup various maximum values after which
+NASM will terminate with a fatal error rather than consume arbitrary
+amount of compute time. Each limit can be set to a positive number or
+\c{unlimited}.
\b\c{--limit-passes}: Number of maximum allowed passes. Default is
-effectively unlimited.
+\c{unlimited}.
\b\c{--limit-stalled-passes}: Maximum number of allowed unfinished
passes. Default is 1000.
\b\c{--limit-macro-levels}: Define maximum depth of macro expansion
-(in preprocess). Default is 1000000.
+(in preprocess). Default is 10000
+
+\b\c{--limit-macro-tokens}: Maximum number of tokens processed during
+single-line macro expansion. Default is 10000000.
+
+\b\c{--limit-mmacros}: Maximum number of multi-line macros processed
+before returning to the top-level input. Default is 100000.
\b\c{--limit-rep}: Maximum number of allowed preprocessor loop, defined
under \c{%rep}. Default is 1000000.
\b\c{--limit-eval}: This number sets the boundary condition of allowed
-expression length. Default is 1000000.
+expression length. Default is 8192 on most systems.
-\b\c{--limit-lines}: Total number of source lines as allowed to be
+\b\c{--limit-lines}: Total number of source lines allowed to be
processed. Default is 2000000000.
-In example, running this limits the maximum line count to be 1000.
+For example, set the maximum line count to 1000:
\c nasm --limit-lines 1000
+Limits can also be set via the directive \c{%pragma limit}, for
+example:
+
+\c %pragma limit lines 1000
+
\S{opt-keep-all} The \i\c{--keep-all} Option
@@ -1088,18 +1141,23 @@ on a misunderstanding by the authors.
For historical reasons, NASM uses the keyword \i\c{TWORD} where MASM
and compatible assemblers use \i\c{TBYTE}.
-NASM does not declare \i{uninitialized storage} in the same way as
-MASM: where a MASM programmer might use \c{stack db 64 dup (?)},
-NASM requires \c{stack resb 64}, intended to be read as `reserve 64
-bytes'. For a limited amount of compatibility, since NASM treats
+Historically, NASM does not declare \i{uninitialized storage} in the
+same way as MASM: where a MASM programmer might use \c{stack db 64 dup
+(?)}, NASM requires \c{stack resb 64}, intended to be read as `reserve
+64 bytes'. For a limited amount of compatibility, since NASM treats
\c{?} as a valid character in symbol names, you can code \c{? equ 0}
and then writing \c{dw ?} will at least do something vaguely useful.
-\I\c{RESB}\i\c{DUP} is still not a supported syntax, however.
+
+As of NASM 2.15, the MASM syntax is also supported.
In addition to all of this, macros and directives work completely
differently to MASM. See \k{preproc} and \k{directive} for further
details.
+\S{masm-compat} MASM compatibility package
+
+See \k{pkg_masm}.
+
\C{lang} The NASM Language
@@ -1141,21 +1199,21 @@ defines a symbol called \c{eax}, you can refer to \c{$eax} in NASM
code to distinguish the symbol from the register. Maximum length of
an identifier is 4095 characters.
-The instruction field may contain any machine instruction: Pentium
-and P6 instructions, FPU instructions, MMX instructions and even
+The instruction field may contain any machine instruction: Pentium and
+P6 instructions, FPU instructions, MMX instructions and even
undocumented instructions are all supported. The instruction may be
prefixed by \c{LOCK}, \c{REP}, \c{REPE}/\c{REPZ}, \c{REPNE}/\c{REPNZ},
-\c{XACQUIRE}/\c{XRELEASE} or \c{BND}/\c{NOBND}, in the usual way. Explicit
-\I{address-size prefixes}address-size and \i{operand-size prefixes} \i\c{A16},
-\i\c{A32}, \i\c{A64}, \i\c{O16} and \i\c{O32}, \i\c{O64} are provided - one example of their use
-is given in \k{mixsize}. You can also use the name of a \I{segment
-override}segment register as an instruction prefix: coding
-\c{es mov [bx],ax} is equivalent to coding \c{mov [es:bx],ax}. We
-recommend the latter syntax, since it is consistent with other
-syntactic features of the language, but for instructions such as
-\c{LODSB}, which has no operands and yet can require a segment
-override, there is no clean syntactic way to proceed apart from
-\c{es lodsb}.
+\c{XACQUIRE}/\c{XRELEASE} or \c{BND}/\c{NOBND}, in the usual
+way. Explicit \I{address-size prefixes}address-size and
+\i{operand-size prefixes} \i\c{A16}, \i\c{A32}, \i\c{A64}, \i\c{O16}
+and \i\c{O32}, \i\c{O64} are provided - one example of their use is
+given in \k{mixsize}. You can also use the name of a \I{segment
+override}segment register as an instruction prefix: coding \c{es mov
+[bx],ax} is equivalent to coding \c{mov [es:bx],ax}. We recommend the
+latter syntax, since it is consistent with other syntactic features of
+the language, but for instructions such as \c{LODSB}, which has no
+operands and yet can require a segment override, there is no clean
+syntactic way to proceed apart from \c{es lodsb}.
An instruction is not required to use a prefix: prefixes such as
\c{CS}, \c{A32}, \c{LOCK} or \c{REPE} can appear on a line by
@@ -1196,10 +1254,11 @@ Pseudo-instructions are things which, though not real x86 machine
instructions, are used in the instruction field anyway because that's
the most convenient place to put them. The current pseudo-instructions
are \i\c{DB}, \i\c{DW}, \i\c{DD}, \i\c{DQ}, \i\c{DT}, \i\c{DO},
-\i\c{DY} and \i\c\{DZ}; their \i{uninitialized} counterparts
-\i\c{RESB}, \i\c{RESW}, \i\c{RESD}, \i\c{RESQ}, \i\c{REST},
-\i\c{RESO}, \i\c{RESY} and \i\c\{RESZ}; the \i\c{INCBIN} command, the
-\i\c{EQU} command, and the \i\c{TIMES} prefix.
+\i\c{DY} and \i\c\{DZ}; their \I{storage,
+uninitialized}\i{uninitialized} counterparts \i\c{RESB}, \i\c{RESW},
+\i\c{RESD}, \i\c{RESQ}, \i\c{REST}, \i\c{RESO}, \i\c{RESY} and
+\i\c\{RESZ}; the \i\c{INCBIN} command, the \i\c{EQU} command, and the
+\i\c{TIMES} prefix.
\S{db} \c{DB} and Friends: Declaring Initialized Data
@@ -1226,6 +1285,49 @@ the output file. They can be invoked in a wide range of ways:
\c{DT}, \c{DO}, \c{DY} and \c{DZ} do not accept \i{numeric constants}
as operands.
+\I{masmdb} Starting in NASM 2.15, a the following \i{MASM}-like features
+have been implemented:
+
+\b A \I{?db}\c{?} argument to declare \i{uninitialized storage}:
+
+\c db ? ; uninitialized
+
+\b A superset of the \i\c{DUP} syntax. The NASM version of this has
+the following syntax specification; capital letters indicate literal
+keywords:
+
+\c dx := DB | DW | DD | DQ | DT | DO | DY | DZ
+\c type := BYTE | WORD | DWORD | QWORD | TWORD | OWORD | YWORD | ZWORD
+\c atom := expression | string | float | '?'
+\c parlist := '(' value [, value ...] ')'
+\c duplist := expression DUP [type] ['%'] parlist
+\c list := duplist | '%' parlist | type ['%'] parlist
+\c value := atom | type value | list
+\c
+\c stmt := dx value [, value...]
+
+\> Note that a \e{list} needs to be prefixed with a \I{%db}\c{%} sign unless
+prefixed by either \c{DUP} or a \e{type} in order to avoid confusing it with
+a parentesis starting an expression. The following expressions are all
+valid:
+
+\c db 33
+\c db (44) ; Integer expression
+\c ; db (44,55) ; Invalid - error
+\c db %(44,55)
+\c db %('XX','YY')
+\c db ('AA') ; Integer expression - outputs single byte
+\c db %('BB') ; List, containing a string
+\c db ?
+\c db 6 dup (33)
+\c db 6 dup (33, 34)
+\c db 6 dup (33, 34), 35
+\c db 7 dup (99)
+\c db 7 dup dword (?, word ?, ?)
+\c dw byte (?,44)
+\c dw 3 dup (0xcc, 4 dup byte ('PQR'), ?), 0xabcd
+\c dd 16 dup (0xaaaa, ?, 0xbbbbbb)
+\c dd 64 dup (?)
\S{resb} \c{RESB} and Friends: Declaring \i{Uninitialized} Data
@@ -1233,11 +1335,9 @@ as operands.
\i\c{RESO}, \i\c{RESY} and \i\c\{RESZ} are designed to be used in the
BSS section of a module: they declare \e{uninitialized} storage
space. Each takes a single operand, which is the number of bytes,
-words, doublewords or whatever to reserve. As stated in \k{qsother},
-NASM does not support the MASM/TASM syntax of reserving uninitialized
-space by writing \I\c{?}\c{DW ?} or similar things: this is what it
-does instead. The operand to a \c{RESB}-type pseudo-instruction is a
-\i\e{critical expression}: see \k{crit}.
+words, doublewords or whatever to reserve. The operand to a
+\c{RESB}-type pseudo-instruction is a \i\e{critical expression}: see
+\k{crit}.
For example:
@@ -1247,13 +1347,23 @@ For example:
\c ymmval: resy 1 ; one YMM register
\c zmmvals: resz 32 ; 32 ZMM registers
+\I{masmdb} Since NASM 2.15, the MASM syntax of using \I{?db}\c{?}
+and \i\c{DUP} in the \c{D}\e{x} directives is also supported. Thus,
+the above example could also be written:
+
+\c buffer: db 64 dup (?) ; reserve 64 bytes
+\c wordvar: dw ? ; reserve a word
+\c realarray dq 10 dup (?) ; array of ten reals
+\c ymmval: dy ? ; one YMM register
+\c zmmvals: dz 32 dup (?) ; 32 ZMM registers
+
+
\S{incbin} \i\c{INCBIN}: Including External \i{Binary Files}
-\c{INCBIN} is borrowed from the old Amiga assembler \i{DevPac}: it
-includes a binary file verbatim into the output file. This can be
-handy for (for example) including \i{graphics} and \i{sound} data
-directly into a game executable file. It can be called in one of
-these three ways:
+\c{INCBIN} includes binary file data verbatim into the output
+file. This can be handy for (for example) including \i{graphics} and
+\i{sound} data directly into a game executable file. It can be called
+in one of these three ways:
\c incbin "file.dat" ; include the whole file
\c incbin "file.dat",1024 ; skip the first 1024 bytes
@@ -1468,7 +1578,7 @@ Some examples (all producing exactly the same code):
\c mov ax,0b1100_1000 ; same binary constant yet again
\c mov ax,0y1100_1000 ; same binary constant yet again
-\S{strings} \I{Strings}\i{Character Strings}
+\S{strings} \I{string}\I{string constants}\i{Character Strings}
A character string consists of up to eight characters enclosed in
either single quotes (\c{'...'}), double quotes (\c{"..."}) or
@@ -1698,12 +1808,71 @@ into the section you are by using \c{($-$$)}.
The arithmetic \i{operators} provided by NASM are listed here, in
increasing order of \i{precedence}.
+A \e{boolean} value is true if nonzero and false if zero. The
+operators which return a boolean value always return 1 for true and 0
+for false.
+
+
+\S{exptri} \I{?op}\c{?} ... \c{:}: Conditional Operator
+
+The syntax of this operator, similar to the C conditional operator, is:
+
+\e{boolean} \c{?} \e{trueval} \c{:} \e{falseval}
+
+This operator evaluates to \e{trueval} if \e{boolean} is true,
+otherwise to \e{falseval}.
+
+Note that NASM allows \c{?} characters in symbol names. Therefore, it
+is highly advisable to always put spaces around the \c{?} and \c{:}
+characters.
+
+
+\S{expbor}: \i\c{||}: \i{Boolean OR} Operator
+
+The \c{||} operator gives a boolean OR: it evaluates to 1 if both sides of
+the expression are nonzero, otherwise 0.
+
+
+\S{expbxor}: \i\c{^^}: \i{Boolean XOR} Operator
+
+The \c{^^} operator gives a boolean XOR: it evaluates to 1 if any one side of
+the expression is nonzero, otherwise 0.
+
+
+\S{expband}: \i\c{&&}: \i{Boolean AND} Operator
+
+The \c{&&} operator gives a boolean AND: it evaluates to 1 if both sides of
+the expression is nonzero, otherwise 0.
+
+
+\S{exprel}: \i{Comparison Operators}
+
+NASM supports the following comparison operators:
+
+\b \i\c{=} or \i\c{==} compare for equality.
+
+\b \i\c{!=} or \i\c{<>} compare for inequality.
+
+\b \i\c{<} compares signed less than.
+
+\b \i\c{<=} compares signed less than or equal.
+
+\b \i\c{>} compares signed greater than.
+
+\b \i\c{>=} compares signed greather than or equal.
+
+These operators evaluate to 0 for false or 1 for true.
+
+\b \i{<=>} does a signed comparison, and evaluates to -1 for less
+than, 0 for equal, and 1 for greater than.
+
+At this time, NASM does not provide unsigned comparison operators.
+
\S{expor} \i\c{|}: \i{Bitwise OR} Operator
The \c{|} operator gives a bitwise OR, exactly as performed by the
-\c{OR} machine instruction. Bitwise OR is the lowest-priority
-arithmetic operator supported by NASM.
+\c{OR} machine instruction.
\S{expxor} \i\c{^}: \i{Bitwise XOR} Operator
@@ -1716,13 +1885,18 @@ arithmetic operator supported by NASM.
\c{&} provides the bitwise AND operation.
-\S{expshift} \i\c{<<} and \i\c{>>}: \i{Bit Shift} Operators
+\S{expshift} \i{Bit Shift} Operators
+
+\i\c{<<} gives a bit-shift to the left, just as it does in C. So
+\c{5<<3} evaluates to 5 times 8, or 40. \i\c{>>} gives an \I{unsigned,
+bit shift}\e{unsigned} (logical) bit-shift to the right; the bits
+shifted in from the left are set to zero.
-\c{<<} gives a bit-shift to the left, just as it does in C. So \c{5<<3}
-evaluates to 5 times 8, or 40. \c{>>} gives a bit-shift to the
-right; in NASM, such a shift is \e{always} unsigned, so that
-the bits shifted in from the left-hand end are filled with zero
-rather than a sign-extension of the previous highest bit.
+\i\c{<<<} gives a bit-shift to the left, exactly equivalent to the
+\c{<<} operator; it is included for completeness. \i\c{>>>} gives an
+\I{signed, bit shift}\e{signed} (arithmetic) bit-shift to the right;
+the bits shifted in from the left are filled with copies of the most
+significant (sign) bit.
\S{expplmi} \I{+ opaddition}\c{+} and \I{- opsubtraction}\c{-}:
@@ -1732,39 +1906,50 @@ The \c{+} and \c{-} operators do perfectly ordinary addition and
subtraction.
-\S{expmul} \i\c{*}, \i\c{/}, \i\c{//}, \i\c{%} and \i\c{%%}:
-\i{Multiplication} and \i{Division}
+\S{expmul} \i{Multiplication}, \i{Division} and \i{Modulo}
-\c{*} is the multiplication operator. \c{/} and \c{//} are both
-division operators: \c{/} is \i{unsigned division} and \c{//} is
-\i{signed division}. Similarly, \c{%} and \c{%%} provide \I{unsigned
-modulo}\I{modulo operators}unsigned and
-\i{signed modulo} operators respectively.
+\i\c{*} is the multiplication operator.
-NASM, like ANSI C, provides no guarantees about the sensible
-operation of the signed modulo operator.
+\i\c{/} and \i\c{//} are both division operators: \c{/} is
+\I{division, unsigned}\I{unsigned, division}unsigned division and \c{//} is
+\I{division, signed}\I{signed, division}signed division.
+
+Similarly, \i\c{%} and \i\c{%%} provide \I{modulo,
+unsigned}\I{unsigned, modulo}unsigned and \I{modulo, signed}\I{signed,
+modulo}signed modulo operators respectively.
Since the \c{%} character is used extensively by the macro
\i{preprocessor}, you should ensure that both the signed and unsigned
modulo operators are followed by white space wherever they appear.
+NASM, like ANSI C, provides no guarantees about the sensible
+operation of the signed modulo operator. On most systems it will match
+the signed division operator, such that:
+
+\c b * (a // b) + (a %% b) = a (b != 0)
+
-\S{expmul} \i{Unary Operators}
+\S{expmul} \I{operators, unary}\i{Unary Operators}
The highest-priority operators in NASM's expression grammar are those
-which only apply to one argument. These are \I{+ opunary}\c{+}, \I{-
-opunary}\c{-}, \i\c{~}, \I{! opunary}\c{!}, \i\c{SEG}, and the
-\i{integer functions} operators.
+which only apply to one argument. These are:
+
+\b \I{- opunary}\c{-} \I{arithmetic negation}negates (\i{2's complement}) its
+operand.
-\c{-} negates its operand, \c{+} does nothing (it's provided for
-symmetry with \c{-}), \c{~} computes the \i{one's complement} of its
-operand, \c{!} is the \i{logical negation} operator.
+\b \I{+ opunary}\c{+} does nothing; it's provided for symmetry with \c{-}.
-\c{SEG} provides the \i{segment address}
-of its operand (explained in more detail in \k{segwrt}).
+\b \I{~ opunary}\c{~} computes the \I{negation, bitwise}\i{bitwise
+negation} (\i{1's complement}) of its operand.
-A set of additional operators with leading and trailing double
-underscores are used to implement the integer functions of the
+\b \I{! opunary}\c{!} is the \I{negation, boolean}\i{boolean negation}
+operator. It evaluates to 1 if the argument is 0, otherwise 0.
+
+\b \c{SEG} provides the \i{segment address} of its operand (explained in
+more detail in \k{segwrt}).
+
+\b A set of additional operators with leading and trailing double
+underscores are used to implement the \c{integer functions} of the
\c{ifunc} macro package, see \k{pkg_ifunc}.
@@ -1775,7 +1960,7 @@ multiple \i{segments}, it is often necessary to be able to refer to
the \I{segment address}segment part of the address of a symbol. NASM
supports the \c{SEG} operator to perform this function.
-The \c{SEG} operator returns the \i\e{preferred} segment base of a
+The \c{SEG} operator evaluates to the \i\e{preferred} segment base of a
symbol, defined as the segment base relative to which the offset of
the symbol makes sense. So the code
@@ -1995,6 +2180,13 @@ not at definition time. Thus the code
will evaluate in the expected way to \c{mov ax,1+2*8}, even though
the macro \c{b} wasn't defined at the time of definition of \c{a}.
+Note that single-line macro argument list cannot be preceded by whitespace.
+Otherwise it will be treated as an expansion. For example:
+
+\c %define foo (a,b) ; no arguments, (a,b) is the expansion
+\c %define bar(a,b) ; two arguments, empty expansion
+
+
Macros defined with \c{%define} are \i{case sensitive}: after
\c{%define foo bar}, only \c{foo} will expand to \c{bar}: \c{Foo} or
\c{FOO} will not. By using \c{%idefine} instead of \c{%define} (the
@@ -2047,6 +2239,39 @@ Then everywhere the macro \c{foo} is invoked, it will be expanded
according to the most recent definition. This is particularly useful
when defining single-line macros with \c{%assign} (see \k{assign}).
+The following additional features were added in NASM 2.15:
+
+It is possible to define an empty string instead of an argument name
+if the argument is never used. For example:
+
+\c %define ereg(foo,) e %+ foo
+\c mov eax,ereg(dx,cx)
+
+A single pair of parentheses is a subcase of a single, unused argument:
+
+\c %define myreg() eax
+\c mov edx,myreg()
+
+This is similar to the behavior of the C preprocessor.
+
+\b If declared with an \c{=}, NASM will evaluate the argument as an
+expression after expansion.
+
+\b If an argument declared with an \c{&}, a macro parameter will be
+turned into a quoted string after expansion.
+
+\b If declared with a \c{+}, it is a greedy or variadic parameter; it
+includes any subsequent commas and parameters.
+
+\b If declared with an \c{!}, NASM will not strip whitespace and
+braces (useful in conjunction with \c{&}).
+
+For example:
+
+\c %define xyzzy(=expr,&val) expr, str
+\c %define plugh(x) xyzzy(x,x)
+\c db plugh(3+5), `\0` ; Expands to: db 8, "3+5", `\0`
+
You can \i{pre-define} single-line macros using the `-d' option on
the NASM command line: see \k{opt-d}.
@@ -2096,6 +2321,9 @@ Now, each time that \c{isFalse} is called, it expands to 1,
as that is what the embedded macro \c{isTrue} expanded to at
the time that \c{isFalse} was defined.
+\c{%xdefine} and \c{%ixdefine} supports argument expansion exactly the
+same way that \c{%define} and \c{%idefine} does.
+
\S{indmacro} \i{Macro Indirection}: \I\c{%[}\c{%[...]}
@@ -2273,6 +2501,58 @@ is equivalent to
\c %define test TEST
+\S{defalias} Defining Aliases: \I\c{%idefalias}\i\c{%defalias}
+
+\c{%defalias}, and its case-insensitive counterpart \c{%idefalias}, define an
+alias to a macro, i.e. equivalent of a symbolic link.
+
+When used with various macro defining and undefining directives, it
+affects the aliased macro. This functionality is intended for being
+able to rename macros while retaining the legacy names.
+
+When an alias is defined, but the aliased macro is then undefined, the
+aliases can legitimately point to nonexistent macros.
+
+The alias can be undefined using the \c{%undefalias} directive. \e{All}
+aliases can be undefined using the \c{%clear defalias} directive. This
+includes backwards compatibility aliases defined by NASM itself.
+
+To disable aliases without undefining them, use the \c{%aliases off}
+directive.
+
+To check whether an alias is defined, regardless of the existence of
+the aliased macro, use \c{%ifdefalias}.
+
+For example:
+
+\c %defalias OLD NEW
+\c ; OLD and NEW both undefined
+\c %define NEW 123
+\c ; OLD and NEW both 123
+\c %undef OLD
+\c ; OLD and NEW both undefined
+\c %define OLD 456
+\c ; OLD and NEW both 456
+\c %undefalias OLD
+\c ; OLD undefined, NEW defined to 456
+
+\S{cond-comma} \i{Conditional Comma Operator}: \i\c{%,}
+
+As of version 2.15, NASM has a conditional comma operator \c{%,} that
+expands to a comma \e{unless} followed by a null expansion, which
+allows suppressing the comma before an empty argument. This is
+especially useful with greedy single-line macros.
+
+For example, all the expressions below are valid:
+
+\c %define greedy(a,b,c+) a + 66 %, b * 3 %, c
+\c
+\c db greedy(1,2) ; db 1 + 66, 2 * 3
+\c db greedy(1,2,3) ; db 1 + 66, 2 * 3, 3
+\c db greedy(1,2,3,4) ; db 1 + 66, 2 * 3, 3, 4
+\c db greedy(1,2,3,4,5) ; db 1 + 66, 2 * 3, 3, 4, 5
+
+
\H{strlen} \i{String Manipulation in Macros}
It's often useful to be able to handle strings in macros. NASM
@@ -2361,7 +2641,7 @@ this.
\c %endmacro
This defines a C-like function prologue as a macro: so you would
-invoke the macro with a call such as
+invoke the macro with a call such as:
\c myfunc: prologue 12
@@ -2384,7 +2664,7 @@ unless you define them using the alternative directive \c{%imacro}.
If you need to pass a comma as \e{part} of a parameter to a
multi-line macro, you can do that by enclosing the entire parameter
in \I{braces, around macro parameters}braces. So you could code
-things like
+things like:
\c %macro silly 2
\c
@@ -2396,6 +2676,15 @@ things like
\c silly 'ab', string_ab ; string_ab: db 'ab'
\c silly {13,10}, crlf ; crlf: db 13,10
+The behavior with regards to empty arguments at the end of multi-line
+macros before NASM 2.15 was often very strange. For backwards
+compatibility, NASM attempts to recognize cases where the legacy
+behavior would give unexpected results, and issues a warning, but
+largely tries to match the legacy behavior. This can be disabled with
+the \c{%pragma} (see \k{pragma-preproc}):
+
+\c %pragma preproc sane_empty_expansion
+
\S{mlmacover} Overloading Multi-Line Macros\I{overloading, multi-line macros}
@@ -2967,20 +3256,6 @@ preprocessor loop: see \k{rep} for a detailed example.
The expression given to \c{%if}, and its counterpart \i\c{%elif}, is
a critical expression (see \k{crit}).
-\c{%if} extends the normal NASM expression syntax, by providing a
-set of \i{relational operators} which are not normally available in
-expressions. The operators \i\c{=}, \i\c{<}, \i\c{>}, \i\c{<=},
-\i\c{>=} and \i\c{<>} test equality, less-than, greater-than,
-less-or-equal, greater-or-equal and not-equal respectively. The
-C-like forms \i\c{==} and \i\c{!=} are supported as alternative
-forms of \c{=} and \c{<>}. In addition, low-priority logical
-operators \i\c{&&}, \i\c{^^} and \i\c{||} are provided, supplying
-\i{logical AND}, \i{logical XOR} and \i{logical OR}. These work like
-the C logical operators (although C has no logical XOR), in that
-they always return either 0 or 1, and treat any non-zero input as 1
-(so that \c{^^}, for example, returns 1 if exactly one of its inputs
-is zero, and 0 otherwise). The relational operators also return 1
-for true and 0 for false.
Like other \c{%if} constructs, \c{%if} has a counterpart
\i\c{%elif}, and negative forms \i\c{%ifn} and \i\c{%elifn}.
@@ -3169,8 +3444,8 @@ infinite loop in the preprocessor, which (on multitasking or
multi-user systems) would typically cause all the system memory to
be gradually used up and other applications to start crashing.
-Note a maximum repeat count is limited by 62 bit number, though it
-is hardly possible that you ever need anything bigger.
+Note the maximum repeat count is limited to the value specified by the
+\c{--limit-rep} option or \c{%pragma limit rep}, see \k{opt-limit}.
\H{files} Source Files and Dependencies
@@ -3265,7 +3540,7 @@ longer true. Thus, the following lines are equivalent:
Standard macro packages are protected from multiple inclusion. When a
standard macro package is used, a testable single-line macro of the
-form \c{__USE_}\e{package}\c{__} is also defined, see \k{use_def}.
+form \c{__?USE_}\e{package}\c{?__} is also defined, see \k{use_def}.
\H{ctxstack} The \i{Context Stack}
@@ -3684,6 +3959,66 @@ the user. For example:
\c %endif
+\H{pragma} \i\c{%pragma}: Setting Options
+
+The \c{%pragma} directive controls a number of options in
+NASM. Pragmas are intended to remain backwards compatible, and
+therefore an unknown \c{%pragma} directive is not an error.
+
+The various pragmas are documented with the options they affect.
+
+The general structure of a NASM pragma is:
+
+\c{%pragma} \e{namespace} \e{directive} [\e{arguments...}]
+
+Currently defined namespaces are:
+
+\b \c{ignore}: this \c{%pragma} is unconditionally ignored.
+
+\b \c{preproc}: preprocessor, see \k{pragma-preproc}.
+
+\b \c{limit}: resource limits, see \k{opt-limit}.
+
+\b \c{asm}: the parser and assembler proper. Currently no such pragmas
+are defined.
+
+\b \c{list}: listing options, see \k{opt-L}.
+
+\b \c{file}: general file handling options. Currently no such pragmas
+are defined.
+
+\b \c{input}: input file handling options. Currently no such pragmas
+are defined.
+
+\b \c{output}: output format options.
+
+\b \c{debug}: debug format options.
+
+In addition, the name of any output or debug format, and sometimes
+groups thereof, also constitue \c{%pragma} namespaces. The namespaces
+\c{output} and \c{debug} simply refer to \e{any} output or debug
+format, respectively.
+
+For example, to prepend an underscore to global symbols regardless of
+the output format (see \k{mangling}):
+
+\c %pragma output gprefix _
+
+... whereas to prepend an underscore to global symbols only when the
+output is either \c{win32} or \c{win64}:
+
+\c %pragma win gprefix _
+
+
+\S{pragma-preproc} Preprocessor Pragmas
+
+The only preprocessor \c{%pragma} defined in NASM 2.15 is:
+
+\b \c{%pragma preproc sane_empty_expansion}: disables legacy
+compatibility handling of braceless empty arguments to multi-line
+macros. See \k{mlmacro} and \k{opt-w}.
+
+
\H{otherpreproc} \i{Other Preprocessor Directives}
\S{line} \i\c{%line} Directive
@@ -3707,7 +4042,8 @@ file which this line corresponds to. \c{mmm} is an optional parameter
which specifies a line increment value; each line of the input file
read in is considered to correspond to \c{mmm} lines of the original
source file. Finally, \c{filename} is an optional parameter which
-specifies the file name of the original source file.
+specifies the file name of the original source file. It may be a
+quoted string.
After reading a \c{%line} preprocessor directive, NASM will report
all file name and line numbers relative to the values specified
@@ -3717,7 +4053,10 @@ If the command line option \i\c{--no-line} is given, all \c{%line}
directives are ignored. This may be useful for debugging preprocessed
code. See \k{opt-no-line}.
+Starting in NASM 2.15, \c{%line} directives are processed before any
+other processing takes place.
+\# This isn't a directive, it should be moved elsewhere...
\S{getenv} \i\c{%!}\e{variable}: Read an Environment Variable.
The \c{%!}\e{variable} directive makes it possible to read the value of an
@@ -3740,29 +4079,66 @@ variable, for example:
\c %defstr C_colon %!'C:'
-\H{stdmac} \i{Standard Macros}
+\S{clear} \i\c\{%clear}: Clear All Macro Definitions
-NASM defines a set of standard macros, which are already defined
-when it starts to process any source file. If you really need a
-program to be assembled with no pre-defined macros, you can use the
-\i\c{%clear} directive to empty the preprocessor of everything but
-context-local preprocessor variables and single-line macros.
+The directive \c{%clear} clears all definitions of a certain type,
+\e{including the ones defined by NASM itself.} This can be useful when
+preprocessing non-NASM code, or to drop backwards compatibility
+aliases.
-Most \i{user-level assembler directives} (see \k{directive}) are
-implemented as macros which invoke primitive directives; these are
-described in \k{directive}. The rest of the standard macro set is
-described here.
+The syntax is:
+\c %clear [global|context] type...
-\S{stdmacver} \i{NASM Version} Macros
+... where \c{context} indicates that this applies to context-local
+macros only; the default is \c{global}.
+
+\c{type} can be one or more of:
+
+\b \c{define} single-line macros
+
+\b \c{defalias} single-line macro aliases (useful to remove backwards
+compatibility aliases)
+
+\b \c{alldefine} same as \c{define defalias}
+
+\b \c{macro} multi-line macros
+
+\b \c{all} same as \c{alldefine macro} (default)
+
+In NASM 2.14 and earlier, only the single syntax \c{%clear} was
+supported, which is equivalent to \c{%clear global all}.
+
+
+
+
+\C{stdmac} \i{Standard Macros}
+
+NASM defines a set of standard macros, which are already defined when
+it starts to process any source file. If you really need a program to
+be assembled with no pre-defined macros, you can use the \i\c{%clear}
+directive to empty the preprocessor of everything but context-local
+preprocessor variables and single-line macros, see \k{clear}.
+
+Most \i{user-level directives} (see \k{directive}) are implemented as
+macros which invoke primitive directives; these are described in
+\k{directive}. The rest of the standard macro set is described here.
+
+For compability with NASM versions before NASM 2.15, most standard
+macros of the form \c{__?foo?__} have aliases of form \c{__foo__} (see
+\k{defalias}). These can be removed with the directive \c{%clear
+defalias}.
+
+
+\H{stdmacver} \i{NASM Version Macros}
The single-line macros \i\c{__?NASM_MAJOR?__}, \i\c{__?NASM_MINOR?__},
-\i\c{__?NASM_SUBMINOR?__} and \i\c{__?_NASM_PATCHLEVEL?__} expand to the
+\i\c{__?NASM_SUBMINOR?__} and \i\c{__?NASM_PATCHLEVEL?__} expand to the
major, minor, subminor and patch level parts of the \i{version
number of NASM} being used. So, under NASM 0.98.32p1 for
example, \c{__?NASM_MAJOR?__} would be defined to be 0, \c{__?NASM_MINOR?__}
would be defined as 98, \c{__?NASM_SUBMINOR?__} would be defined to 32,
-and \c{__?_NASM_PATCHLEVEL?__} would be defined as 1.
+and \c{__?NASM_PATCHLEVEL?__} would be defined as 1.
Additionally, the macro \i\c{__?NASM_SNAPSHOT?__} is defined for
automatically generated snapshot releases \e{only}.
@@ -3773,7 +4149,7 @@ automatically generated snapshot releases \e{only}.
The single-line macro \c{__?NASM_VERSION_ID?__} expands to a dword integer
representing the full version number of the version of nasm being used.
The value is the equivalent to \c{__?NASM_MAJOR?__}, \c{__?NASM_MINOR?__},
-\c{__?NASM_SUBMINOR?__} and \c{__?_NASM_PATCHLEVEL?__} concatenated to
+\c{__?NASM_SUBMINOR?__} and \c{__?NASM_PATCHLEVEL?__} concatenated to
produce a single doubleword. Hence, for 0.98.32p1, the returned number
would be equivalent to:
@@ -3788,7 +4164,7 @@ line is used just to give an indication of the order that the separate
values will be present in memory.
-\S{stdmacverstr} \i\c{__?NASM_VER?__}: \i{NASM Version string}
+\S{stdmacverstr} \i\c{__?NASM_VER?__}: \i{NASM Version String}
The single-line macro \c{__?NASM_VER?__} expands to a string which defines
the version number of nasm being used. So, under NASM 0.98.32 for example,
@@ -3800,7 +4176,7 @@ would expand to
\c db "0.98.32"
-\S{fileline} \i\c{__?FILE?__} and \i\c{__?LINE?__}: File Name and Line Number
+\H{fileline} \i\c{__?FILE?__} and \i\c{__?LINE?__}: File Name and Line Number
Like the C preprocessor, NASM allows the user to find out the file
name and line number containing the current instruction. The macro
@@ -3815,8 +4191,8 @@ definition (either single-line or multi-line) will return the line
number of the macro \e{call}, rather than \e{definition}. So to
determine where in a piece of code a crash is occurring, for
example, one could write a routine \c{stillhere}, which is passed a
-line number in \c{EAX} and outputs something like `line 155: still
-here'. You could then write a macro
+line number in \c{EAX} and outputs something like \c{line 155: still
+here}. You could then write a macro:
\c %macro notdeadyet 0
\c
@@ -3831,7 +4207,7 @@ and then pepper your code with calls to \c{notdeadyet} until you
find the crash point.
-\S{bitsm} \i\c{__?BITS?__}: Current BITS Mode
+\H{bitsm} \i\c{__?BITS?__}: Current Code Generation Mode
The \c{__?BITS?__} standard macro is updated every time that the BITS mode is
set using the \c{BITS XX} or \c{[BITS XX]} directive, where XX is a valid mode
@@ -3839,11 +4215,11 @@ number of 16, 32 or 64. \c{__?BITS?__} receives the specified mode number and
makes it globally available. This can be very useful for those who utilize
mode-dependent macros.
-\S{ofmtm} \i\c{__?OUTPUT_FORMAT?__}: Current Output Format
+\H{ofmtm} \i\c{__?OUTPUT_FORMAT?__}: Current Output Format
The \c{__?OUTPUT_FORMAT?__} standard macro holds the current output
format name, as given by the \c{-f} option or NASM's default. Type
-\c{nasm -hf} for a list.
+\c{nasm -h} for a list.
\c %ifidn __?OUTPUT_FORMAT?__, win32
\c %define NEWLINE 13, 10
@@ -3851,7 +4227,7 @@ format name, as given by the \c{-f} option or NASM's default. Type
\c %define NEWLINE 10
\c %endif
-\S{dfmtm} \i\c{__?DEBUG_FORMAT?__}: Current Debug Format
+\H{dfmtm} \i\c{__?DEBUG_FORMAT?__}: Current Debug Format
If debugging information generation is enabled, The
\c{__?DEBUG_FORMAT?__} standard macro holds the current debug format
@@ -3861,7 +4237,7 @@ default. Type \c{nasm -f} \e{output} \c{y} for a list.
\c{__?DEBUG_FORMAT?__} is not defined if debugging is not enabled, or if
the debug format specified is \c{null}.
-\S{datetime} Assembly Date and Time Macros
+\H{datetime} Assembly Date and Time Macros
NASM provides a variety of macros that represent the timestamp of the
assembly session.
@@ -3909,7 +4285,7 @@ clock:
\c __?POSIX_TIME?__ 1262293242
-\S{use_def} \I\c{__USE_*__}\c{__USE_}\e{package}\c{__}: Package
+\H{use_def} \I\c{__?USE_*?__}\c{__?USE_}\e{package}\c{?__}: Package
Include Test
When a standard macro package (see \k{macropkg}) is included with the
@@ -3921,7 +4297,7 @@ For example, if the \c{altreg} package is included (see
\k{pkg_altreg}), then the macro \c{__?USE_ALTREG?__} is defined.
-\S{pass_macro} \i\c{__?PASS?__}: Assembly Pass
+\H{pass_macro} \i\c{__?PASS?__}: Assembly Pass
The macro \c{__?PASS?__} is defined to be \c{1} on preparatory passes,
and \c{2} on the final pass. In preprocess-only mode, it is set to
@@ -3933,6 +4309,8 @@ to generate very strange errors by misusing it, and the semantics may
change in future versions of NASM.}
+\H{strucs} \i{Structure Data Types}
+
\S{struc} \i\c{STRUC} and \i\c{ENDSTRUC}: \i{Declaring Structure} Data Types
The core of NASM contains no intrinsic means of defining data
@@ -4053,8 +4431,9 @@ line:
\c db 'hello, world'
\c db 13,10,0
+\H{alignment} \i{Alignment} Control
-\S{align} \i\c{ALIGN} and \i\c{ALIGNB}: Data Alignment
+\S{align} \i\c{ALIGN} and \i\c{ALIGNB}: Code and Data Alignment
The \c{ALIGN} and \c{ALIGNB} macros provides a convenient way to
align code or data on a word, longword, paragraph or other boundary.
@@ -4145,6 +4524,8 @@ It is still possible to turn in on again by
\c SECTALIGN ON
+Note that \c{SECTALIGN <ON|OFF>} affects only the \c{ALIGN}/\c{ALIGNB} directives,
+not an explicit \c{SECTALIGN} directive.
\C{macropkg} \i{Standard Macro Packages}
@@ -4153,9 +4534,13 @@ macro packages included with the NASM distribution and compiled into
the NASM binary. It operates like the \c{%include} directive (see
\k{include}), but the included contents is provided by NASM itself.
-The names of standard macro packages are case insensitive, and can be
+The names of standard macro packages are case insensitive and can be
quoted or not.
+As of version 2.15, NASM has \c{%ifusable} and \c{%ifusing} directives to help
+the user understand whether an individual package available in this version of
+NASM (\c{%ifusable}) or a particular package already loaded (\c{%ifusing}).
+
\H{pkg_altreg} \i\c{altreg}: \i{Alternate Register Names}
@@ -4268,6 +4653,24 @@ The functions \i\c{ilog2fw()} (alias \i\c{ilog2w()}) and
two, but otherwise behaves like \c{ilog2f()} and \c{ilog2c()},
respectively.
+\H{pkg_masm} \i\c{masm}: \i{MASM compatibility}
+
+Since version 2.15, NASM has a MASM compatibility package with minimal
+functionality, as intended to be used primarily with machine-generated code.
+It does not include any "programmer-friendly" shortcuts, nor does it in any way
+support ASSUME, symbol typing, or MASM-style structures.
+
+Currently, the MASM compatibility package emulates only the PTR
+keyword and recognize syntax displacement[index] for memory
+operations.
+To enable the package, use the directive:
+
+\c{%use masm}
+
+In addition, NASM now natively supports the MASM \c{?} and
+\c{DUP} syntax for the \c{DB} etc data declaration directives,
+regardless of if this package is included or not. See \k{db}.
+
\C{directive} \i{Assembler Directives}
@@ -4560,6 +4963,16 @@ declared as \c{EXTERN} and then defined, it will be treated as
\c{EXTERN}, it will be treated as \c{COMMON}.
+\H{required} \i\c{REQUIRED}: \i{Unconditionally Importing Symbols} from Other Modules
+
+The \c{REQUIRED} keyword is similar to \c{EXTERN} one. The difference
+is that the \c{EXTERN} keyword as of version 2.15 does not generate
+unknown symbols as that prevents using common header files, as it
+might cause the linker to pull in a bunch of unnecessary modules.
+
+If the old behavior is required, use \c{REQUIRED} keyword instead.
+
+
\H{global} \i\c{GLOBAL}: \i{Exporting Symbols} to Other Modules
\c{GLOBAL} is the other end of \c{EXTERN}: if one module declares a
@@ -4636,27 +5049,36 @@ private extensions mentioned in \k{global}.
\H{mangling} \i\c{(G|L)PREFIX}, \i\c{(G|L)POSTFIX}: Mangling Symbols
\c{PREFIX}, \c{GPREFIX}, \c{LPREFIX}, \c{POSTFIX}, \c{GPOSTFIX}, and
-\c{LPOSTFIX} directives can prepend or append the given argument to
-a certain type of symbols. The directive should be as a preprocess
-statement. Each usage is:
+\c{LPOSTFIX} directives can prepend or append a string to a certain
+type of symbols, normally to fit specific ABI conventions
\b\c{PREFIX}|\c{GPREFIX}: Prepend the argument to all \c{EXTERN}
-\c{COMMON}, \c{STATIC}, and \c{GLOBAL} symbols
+\c{COMMON}, \c{STATIC}, and \c{GLOBAL} symbols.
\b\c{LPREFIX}: Prepend the argument to all other symbols
-such as Local Labels, and backend defined symbols
+such as local labels and backend defined symbols.
\b\c{POSTFIX}|\c{GPOSTFIX}: Append the argument to all \c{EXTERN}
-\c{COMMON}, \c{STATIC}, and \c{GLOBAL} symbols
+\c{COMMON}, \c{STATIC}, and \c{GLOBAL} symbols.
\b\c{LPOSTFIX}: Append the argument to all other symbols
-such as Local Labels, and backend defined symbols
+such as local labels and backend defined symbols.
+
+These a macros implemented as pragmas, and using \c{%pragma} syntax
+can be restricted to specific backends (see \k{pragma}):
-This is a macro implemented as a \c{%pragma}:
+\c %pragma macho lprefix L_
-\c %pragma macho lprefix L_
+Command line options are also available. See also \k{opt-pfix}.
-Commandline option is also possible. See also \k{opt-pfix}.
+One example which supports many ABIs:
+
+\c ; The most common conventions
+\c %pragma output gprefix _
+\c %pragma output lprefix L_
+\c ; ELF uses a different convention
+\c %pragma elf gprefix ; empty
+\c %pragma elf lprefix .L
Some toolchains is aware of a particular prefix for its own optimization
options, such as code elimination. For instance, Mach-O backend has a
@@ -4671,22 +5093,6 @@ Note that local symbols declared with \c{STATIC} (\k{static})
are excluded from the symbol mangling and also not marked as global.
-\H{gen-namespace} \i\c{OUTPUT}, \i\c{DEBUG}: Generic Namespaces
-
-\c{OUTPUT} and \c{DEBUG} are generic \c{%pragma} namespaces that are
-supposed to redirect to the current output and debug formats.
-For example, when mangling local symbols via the generic namespace:
-
-\c %pragma output gprefix _
-
-This is useful when the directive is needed to be output format
-agnostic.
-
-The example is also euquivalent to this, when the output format is ELF:
-
-\c %pragma elf gprefix _
-
-
\H{CPU} \i\c{CPU}: Defining CPU Dependencies
The \i\c{CPU} directive restricts assembly to those instructions which
@@ -4851,7 +5257,7 @@ does. See \k{proborg} for further comments.
\S{binseg} \c{bin} Extensions to the \c{SECTION}
-Directive\I{SECTION, bin extensions to}
+Directive\I{\c{SECTION}, \c{bin} extensions to}
The \c{bin} output format extends the \c{SECTION} (or \c{SEGMENT})
directive to allow you to specify the alignment requirements of
@@ -5164,7 +5570,7 @@ be specified, even if it is the same as the internal name. The
available attributes are:
\b \c{resident} indicates that the exported name is to be kept
-resident by the system loader. This is an optimisation for
+resident by the system loader. This is an optimization for
frequently used symbols imported by name.
\b \c{nodata} indicates that the exported symbol is a function which
@@ -5308,7 +5714,7 @@ files that Win32 linkers can generate correct output from.
\S{win32sect} \c{win32} Extensions to the \c{SECTION}
-Directive\I{SECTION, win32 extensions to}
+Directive\I{SECTION, Windows extensions to}
Like the \c{obj} format, \c{win32} allows you to specify additional
information on the \c{SECTION} directive line, to control the type
@@ -5454,8 +5860,8 @@ later can still be linked by earlier versions or non-Microsoft linkers.
\S{codeview} Debugging formats for Windows
\I{Windows debugging formats}
-The \c{win32} and \c{win64} formats support the Microsoft CodeView
-debugging format. Currently CodeView version 8 format is supported
+The \c{win32} and \c{win64} formats support the Microsoft \i{CodeView
+debugging format}. Currently CodeView version 8 format is supported
(\i\c{cv8}), but newer versions of the CodeView debugger should be
able to handle this format as well.
@@ -6027,14 +6433,14 @@ of the symbol with code such as:
\S{elfglob} \c{elf} Extensions to the \c{GLOBAL} Directive\I{GLOBAL,
elf extensions to}\I{GLOBAL, aoutb extensions to}
-\c{ELF} object files can contain more information about a global symbol
-than just its address: they can contain the \I{symbol sizes,
-specifying}\I{size, of symbols}size of the symbol and its \I{symbol
-types, specifying}\I{type, of symbols}type as well. These are not
-merely debugger conveniences, but are actually necessary when the
-program being written is a \i{shared library}. NASM therefore
-supports some extensions to the \c{GLOBAL} directive, allowing you
-to specify these features.
+\c{ELF} object files can contain more information about a global
+symbol than just its address: they can contain the \I{symbols,
+specifying sizes}\I{size, of symbols}size of the symbol and its
+\I{symbols, specifying types}\I{type, of symbols}type as well. These
+are not merely debugger conveniences, but are actually necessary when
+the program being written is a \I{elf shared library}shared
+library. NASM therefore supports some extensions to the \c{GLOBAL}
+directive, allowing you to specify these features.
You can specify whether a global variable is a function or a data
object by suffixing the name with a colon and the word
@@ -6053,6 +6459,9 @@ course. For example, to make \c{hashlookup} hidden:
\c global hashlookup:function hidden
+Since version 2.15, it is possible to specify symbols binding. The keywords
+are: \i\c{weak} to generate weak symbol or \i\c{strong}. The default is \i\c{strong}.
+
You can also specify the size of the data associated with the
symbol, as a numeric expression (which may involve labels, and even
forward references) after the type specifier. Like this:
@@ -6071,6 +6480,15 @@ writing shared library code. For more information, see
\k{picglobal}.
+\S{elfextrn} \c{elf} Extensions to the \c{EXTERN} Directive\I{EXTERN,
+elf extensions to}\I{EXTERN, elf extensions to}
+
+Since version 2.15 it is possible to specify keyword \i\c{weak} to generate weak external
+reference. Example:
+
+\c extern weak_ref:weak
+
+
\S{elfcomm} \c{elf} Extensions to the \c{COMMON} Directive
\I{COMMON, elf extensions to}
@@ -6326,7 +6744,7 @@ also, have to be built as \c{.EXE} files, since Windows does not
support the \c{.COM} format.
In general, you generate \c{.EXE} files by using the \c{obj} output
-format to produce one or more \i\c{.OBJ} files, and then linking
+format to produce one or more \i\c{.obj} files, and then linking
them together using a linker. However, NASM also supports the direct
generation of simple DOS \c{.EXE} files using the \c{bin} output
format (by using \c{DB} and \c{DW} to construct the \c{.EXE} file
@@ -7651,11 +8069,11 @@ You would then copy \c{library.so.1.2} into the library directory,
and create \c{library.so.1} as a symbolic link to it.
-\C{mixsize} Mixing 16 and 32 Bit Code
+\C{mixsize} Mixing 16- and 32-bit Code
This chapter tries to cover some of the issues, largely related to
unusual forms of addressing and jump instructions, encountered when
-writing operating system code such as protected-mode initialisation
+writing operating system code such as protected-mode initialization
routines, which require code that operates in mixed segment sizes,
such as code in a 16-bit segment trying to modify data in a 32-bit
one, or jumps between different-size segments.
@@ -8166,7 +8584,7 @@ Hence, to disassemble a \c{.COM} file:
will do the trick.
-\S{ndissync} Code Following Data: Synchronisation
+\S{ndissync} Code Following Data: Synchronization
Suppose you are disassembling a file which contains some data which
isn't machine code, and \e{then} contains some machine code. NDISASM
@@ -8185,8 +8603,8 @@ then the correct first instruction in the code section will not be
seen because the starting point skipped over it. This isn't really
ideal.
-To avoid this, you can specify a `\i{synchronisation}' point, or indeed
-as many synchronisation points as you like (although NDISASM can
+To avoid this, you can specify a `\i{synchronization}' point, or indeed
+as many synchronization points as you like (although NDISASM can
only handle 2147483647 sync points internally). The definition of a sync
point is this: NDISASM guarantees to hit sync points exactly during
disassembly. If it is thinking about generating an instruction which
@@ -8210,7 +8628,7 @@ As stated above, you can specify multiple sync markers if you need
to, just by repeating the \c{-s} option.
-\S{ndisisync} Mixed Code and Data: Automatic (Intelligent) Synchronisation
+\S{ndisisync} Mixed Code and Data: Automatic (Intelligent) Synchronization
\I\c{auto-sync}
Suppose you are disassembling the boot sector of a \c{DOS} floppy (maybe
@@ -8329,8 +8747,9 @@ the \c{git} distributed source control system. The link is available
on the website. This is recommended only to participate in the
development of NASM or to assist with testing the development code.
-To build NASM from the \c{git} repository you will need a Perl and, if
-building on a Unix system, GNU autoconf.
+To build NASM from the \c{git} repository you will need a Perl
+interpreter and, if building on a Unix system, GNU autoconf installed
+on your system.
To build on a Unix system, run:
@@ -8338,6 +8757,14 @@ To build on a Unix system, run:
to create the \c{configure} script and then build as listed above.
+\H{builddoc} Building the documentation
+
+To build the documentation, you will need a Perl interpreter, a
+Postscript to PDF converter such as Ghostscript, and suitable fonts
+installed on your system. The recommended (and default) fonts are
+Adobe's Source Sans and Source Code fonts, which are freely available
+under the SIL Open Font License.
+
\A{contact} Contact Information
\H{website} Website
diff --git a/doc/psfonts.ph b/doc/psfonts.ph
index 093d9dc4..9ebbe09d 100644
--- a/doc/psfonts.ph
+++ b/doc/psfonts.ph
@@ -21,33 +21,54 @@ my @QText = ('SourceSansPro-It', 'ClearSans-Italic', 'LiberationSans-Italic',
'Arial-Italic', 'Helvetica-Italic');
my @QBold = ('SourceSansPro-BoldIt', 'ClearSans-BoldItalic', 'LiberationSans-BoldItalic', 'Arial-Bold', 'Helvetica-BoldItalic');
my @QCode = ('SourceCodePro-Regular', 'LiberationMono', 'Courier');
+my @XCode = ('SourceCodePro-Regular', 'LiberationMono', 'Courier');
# The fonts we want to use for various things
# The order is: <normal> <emphatic> <code>
+my $lf = 1.2; # Leading scale factor
+my $cf = 0.8; # Code size scale factor
+
+my $st = 20;
%TitlFont = (name => 'tfont',
- leading => 24,
- fonts => [[20, \@TText], [20, \@TItal], [20, \@TCode]]);
+ leading => $st*$lf,
+ fonts => [[$st, \@TText], [$st, \@TItal], [$st*$cf, \@TCode]]);
+
+my $sc = 18;
%ChapFont = (name => 'cfont',
- leading => 21.6,
- fonts => [[18, \@HText], [18, \@HItal], [18, \@HCode]]);
+ leading => $sc*$lf,
+ fonts => [[$sc, \@HText], [$sc, \@HItal], [$sc*$cf, \@HCode]]);
+
+my $sh = 14;
%HeadFont = (name => 'hfont',
- leading => 16.8,
- fonts => [[14, \@HText], [14, \@HItal], [14, \@HCode]]);
+ leading => $sh*$lf,
+ fonts => [[$sh, \@HText], [$sh, \@HItal], [$sh*$cf, \@HCode]]);
+
+my $ss = 12;
%SubhFont = (name => 'sfont',
- leading => 14.4,
- fonts => [[12, \@HText], [12, \@HItal], [12, \@HCode]]);
+ leading => $ss*$lf,
+ fonts => [[$ss, \@HText], [$ss, \@HItal], [$ss*$cf, \@HCode]]);
+
+my $sb = 10;
%BodyFont = (name => 'bfont',
- leading => 12,
- fonts => [[10, \@BText], [10, \@BItal], [10, \@BCode]]);
+ leading => $sb*$lf,
+ fonts => [[$sb, \@BText], [$sb, \@BItal], [$sb*$cf, \@BCode]]);
+
+my $sq = 9;
%BquoFont = (name => 'qfont',
- leading => 10.8,
- fonts => [[9, \@QText], [9, \@QBold], [9, \@QCode]]);
+ leading => $sq*$lf,
+ fonts => [[$sq, \@QText], [$sq, \@QBold], [$sq*$cf, \@QCode]]);
+
+my $sx = $sb*$cf;
+%CodeFont = (name => 'xfont',
+ leading => $sx*$lf,
+ fonts => [[$sx, \@XCode], [$sx, \@XCode], [$sx, \@XCode]]);
+
#
# List of all fontsets; used to compute the list of fonts needed
#
@AllFonts = ( \%TitlFont, \%ChapFont, \%HeadFont, \%SubhFont, \%BodyFont,
- \%BquoFont);
+ \%BquoFont, \%CodeFont );
# OK
1;
diff --git a/doc/pspdf.pl b/doc/pspdf.pl
index 569f974b..91986413 100755
--- a/doc/pspdf.pl
+++ b/doc/pspdf.pl
@@ -18,7 +18,7 @@ while ($ARGV[0] =~ /^-(.*)$/) {
my $opt = $1;
shift @ARGV;
- if ($opt eq '-nocompress') {
+ if ($opt eq 'nocompress') {
$compress = 0;
}
}
@@ -114,11 +114,13 @@ if (defined($fontpath)) {
$fpopt = "-sFONTPATH${o}" . join($p, @fplist);
}
-my $r = system($gs, "-dCompatibilityLevel${o}1.4",
+my $r = system($gs, "-dCompatibilityLevel${o}1.3",
"-I".File::Spec->curdir(),
"-P-", "-dNOPAUSE", "-dBATCH", "-sDEVICE${o}pdfwrite",
"-sstdout${o}%stderr", "-sOutputFile${o}${out}",
- "-dOptimize${o}true", "-dEmbedAllFonts${o}true",
+ "-dOptimize${o}true",
+ "-dEmbedAllFonts${o}true", "-dSubsetFonts${o}true",
+ "-dMaxSubsetPct${o}100",
$fpopt,
"-dCompressPages${o}" . ($compress ? 'true' : 'false'),
"-dUseFlateCompression${o}true",
diff --git a/include/compiler.h b/include/compiler.h
index 04cab173..a1c1b0db 100644
--- a/include/compiler.h
+++ b/include/compiler.h
@@ -1,5 +1,5 @@
/* ----------------------------------------------------------------------- *
- *
+ *
* Copyright 2007-2018 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
@@ -14,7 +14,7 @@
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
@@ -88,6 +88,7 @@
#include <stdlib.h>
#include <string.h>
#include <limits.h>
+#include <errno.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
@@ -359,6 +360,13 @@ static inline void *mempcpy(void *dst, const void *src, size_t n)
# endif
#endif
+/*
+ * If SIZE_MAX is not defined, rely on size_t being unsigned
+ */
+#ifndef SIZE_MAX
+# define SIZE_MAX (((size_t)0) - 1)
+#endif
+
/* Watcom doesn't handle switch statements with 64-bit types, hack around it */
#ifdef __WATCOMC__
# define BOGUS_CASE 0x76543210
diff --git a/include/error.h b/include/error.h
index 3bfe30a6..d5dc65da 100644
--- a/include/error.h
+++ b/include/error.h
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2019 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2020 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -99,13 +99,14 @@ fatal_func nasm_verror_critical(errflags severity, const char *fmt, va_list ap);
#define ERR_NO_SEVERITY 0x00000200 /* suppress printing severity */
#define ERR_PP_PRECOND 0x00000400 /* for preprocessor use */
#define ERR_PP_LISTMACRO 0x00000800 /* from preproc->error_list_macros() */
+#define ERR_HOLD 0x00001000 /* this error/warning can be held */
/*
* These codes define specific types of suppressible warning.
* They are assumed to occupy the most significant bits of the
* severity code.
*/
-#define WARN_SHR 12 /* how far to shift right */
+#define WARN_SHR 16 /* how far to shift right */
#define WARN_IDX(x) (((errflags)(x)) >> WARN_SHR)
#define WARN_MASK ((~(errflags)0) << WARN_SHR)
@@ -127,6 +128,21 @@ void pop_warnings(void);
void init_warnings(void);
void reset_warnings(void);
+/*
+ * Tentative error hold for warnings/errors indicated with ERR_HOLD.
+ *
+ * This is a stack; the "hold" argument *must*
+ * match the value returned from nasm_error_hold_push().
+ * If "issue" is true the errors are committed (or promoted to the next
+ * higher stack level), if false then they are discarded.
+ *
+ * Errors stronger than ERR_NONFATAL cannot be held.
+ */
+struct nasm_errhold;
+typedef struct nasm_errhold *errhold;
+errhold nasm_error_hold_push(void);
+void nasm_error_hold_pop(errhold hold, bool issue);
+
/* Should be included from within error.h only */
#include "warnings.h"
diff --git a/include/nasm.h b/include/nasm.h
index 2a207a03..616ffb37 100644
--- a/include/nasm.h
+++ b/include/nasm.h
@@ -428,7 +428,6 @@ static inline char *nasm_skip_identifier(const char *str)
enum {
LIST_READ,
LIST_MACRO,
- LIST_MACRO_NOLIST,
LIST_INCLUDE,
LIST_INCBIN,
LIST_TIMES
@@ -462,6 +461,7 @@ enum ccode { /* condition code names */
#define TFLAG_BRC_ANY (TFLAG_BRC | TFLAG_BRC_OPT)
#define TFLAG_BRDCAST (1 << 2) /* broadcasting decorator */
#define TFLAG_WARN (1 << 3) /* warning only, treat as ID */
+#define TFLAG_DUP (1 << 4) /* valid ID but also has context-specific use */
static inline uint8_t get_cond_opcode(enum ccode c)
{
@@ -548,13 +548,6 @@ enum prefixes { /* instruction prefixes */
PREFIX_ENUM_LIMIT
};
-enum extop_type { /* extended operand types */
- EOT_NOTHING,
- EOT_DB_STRING, /* Byte string */
- EOT_DB_STRING_FREE, /* Byte string which should be nasm_free'd*/
- EOT_DB_NUMBER /* Integer */
-};
-
enum ea_flags { /* special EA flags */
EAF_BYTEOFFS = 1, /* force offset part to byte size */
EAF_WORDOFFS = 2, /* force offset part to [d]word size */
@@ -595,15 +588,34 @@ typedef struct operand { /* operand to an instruction */
#define OPFLAG_RELATIVE 8 /* operand is self-relative, e.g. [foo - $]
where foo is not in the current segment */
+enum extop_type { /* extended operand types */
+ EOT_NOTHING = 0,
+ EOT_EXTOP, /* Subexpression */
+ EOT_DB_STRING, /* Byte string */
+ EOT_DB_FLOAT, /* Floating-pointer number (special byte string) */
+ EOT_DB_STRING_FREE, /* Byte string which should be nasm_free'd*/
+ EOT_DB_NUMBER, /* Integer */
+ EOT_DB_RESERVE /* ? */
+};
+
typedef struct extop { /* extended operand */
- struct extop *next; /* linked list */
- char *stringval; /* if it's a string, then here it is */
- size_t stringlen; /* ... and here's how long it is */
- int64_t offset; /* ... it's given here ... */
- int32_t segment; /* if it's a number/address, then... */
- int32_t wrt; /* ... and here */
- bool relative; /* self-relative expression */
- enum extop_type type; /* defined above */
+ struct extop *next; /* linked list */
+ union {
+ struct { /* text or byte string */
+ char *data;
+ size_t len;
+ } string;
+ struct { /* numeric expression */
+ int64_t offset; /* numeric value or address offset */
+ int32_t segment; /* address segment */
+ int32_t wrt; /* address wrt */
+ bool relative; /* self-relative expression */
+ } num;
+ struct extop *subexpr; /* actual expressions */
+ } val;
+ size_t dup; /* duplicated? */
+ enum extop_type type; /* defined above */
+ int elem; /* element size override, if any (bytes) */
} extop;
enum ea_type {
@@ -827,7 +839,7 @@ struct ofmt {
* This procedure is called at the start of each pass.
*/
void (*reset)(void);
-
+
/*
* This is the modern output function, which gets passed
* a struct out_data with much more information. See the
@@ -1252,8 +1264,8 @@ enum decorator_tokens {
* Global modes
*/
-/*
- * flag to disable optimizations selectively
+/*
+ * flag to disable optimizations selectively
* this is useful to turn-off certain optimizations
*/
enum optimization_disable_flag {
@@ -1271,6 +1283,7 @@ struct optimization {
*/
enum pass_type {
PASS_INIT, /* Initialization, not doing anything yet */
+ PASS_PREPROC, /* Preprocess-only mode (similar to PASS_FIRST) */
PASS_FIRST, /* The very first pass over the code */
PASS_OPT, /* Optimization pass */
PASS_STAB, /* Stabilization pass (original pass 1) */
@@ -1306,6 +1319,11 @@ static inline bool pass_final(void)
{
return pass_type() >= PASS_FINAL;
}
+/* True for code generation *or* preprocess-only mode */
+static inline bool pass_final_or_preproc(void)
+{
+ return pass_type() >= PASS_FINAL || pass_type() == PASS_PREPROC;
+}
/*
* The actual pass number. 0 is used during initialization, the very
@@ -1331,4 +1349,4 @@ extern const char *outname; /* output filename */
*/
int64_t switch_segment(int32_t segment);
-#endif
+#endif /* NASM_NASM_H */
diff --git a/include/nasmlib.h b/include/nasmlib.h
index 2e2519f5..e9bfbccf 100644
--- a/include/nasmlib.h
+++ b/include/nasmlib.h
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2018 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2020 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -355,12 +355,18 @@ enum file_flags {
NF_TEXT = 0x00000001, /* Text file */
NF_NONFATAL = 0x00000000, /* Don't die on open failure (default) */
NF_FATAL = 0x00000002, /* Die on open failure */
- NF_FORMAP = 0x00000004 /* Intended to use nasm_map_file() */
+ NF_FORMAP = 0x00000004, /* Intended to use nasm_map_file() */
+ NF_IONBF = 0x00000010, /* Force unbuffered stdio */
+ NF_IOLBF = 0x00000020, /* Force line buffered stdio */
+ NF_IOFBF = 0000000030 /* Force fully buffered stdio */
};
+#define NF_BUF_MASK 0x30
FILE *nasm_open_read(const char *filename, enum file_flags flags);
FILE *nasm_open_write(const char *filename, enum file_flags flags);
+void nasm_set_binary_mode(FILE *f);
+
/* Probe for existence of a file */
bool nasm_file_exists(const char *filename);
@@ -450,4 +456,7 @@ static inline int64_t const_func signed_bits(int64_t value, int bits)
/* check if value is power of 2 */
#define is_power2(v) ((v) && ((v) & ((v) - 1)) == 0)
+/* try to get the system stack size */
+extern size_t nasm_get_stack_size_limit(void);
+
#endif
diff --git a/include/rbtree.h b/include/rbtree.h
index f0ffb914..8ccd129c 100644
--- a/include/rbtree.h
+++ b/include/rbtree.h
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
- *
- * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ *
+ * Copyright 1996-2020 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -14,7 +14,7 @@
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
@@ -36,16 +36,47 @@
#include "compiler.h"
-/* This structure should be embedded in a larger data structure;
- the final output from rb_search() can then be converted back
- to the larger data structure via container_of(). */
+/*
+ * This structure should be embedded in a larger data structure;
+ * the final output from rb_search() can then be converted back
+ * to the larger data structure via container_of().
+ *
+ * An empty tree is simply represented by a NULL pointer.
+ */
+
+/* Note: the values of these flags is significant */
+enum rbtree_node_flags {
+ RBTREE_NODE_BLACK = 1, /* Node color is black */
+ RBTREE_NODE_PRED = 2, /* Left pointer is an uplink */
+ RBTREE_NODE_SUCC = 4 /* Right pointer is an uplink */
+};
+
struct rbtree {
uint64_t key;
- struct rbtree *left, *right;
- bool red;
+ struct rbtree_metadata {
+ struct rbtree *left, *right;
+ enum rbtree_node_flags flags;
+ } m;
};
+/*
+ * Add a node to a tree. Returns the new root pointer.
+ * The key value in the structure needs to be preinitialized;
+ * the rest of the structure should be zero.
+ */
struct rbtree *rb_insert(struct rbtree *, struct rbtree *);
-struct rbtree *rb_search(struct rbtree *, uint64_t);
+
+/*
+ * Find a node in the tree corresponding to the key immediately
+ * <= the passed-in key value.
+ */
+struct rbtree *rb_search(const struct rbtree *, uint64_t);
+
+/*
+ * Return the immediately previous or next node in key order.
+ * Returns NULL if this node is the end of the
+ */
+struct rbtree *rb_prev(const struct rbtree *);
+struct rbtree *rb_next(const struct rbtree *);
#endif /* NASM_RBTREE_H */
diff --git a/include/strlist.h b/include/strlist.h
index 2c80d0be..25681c59 100644
--- a/include/strlist.h
+++ b/include/strlist.h
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2018 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2020 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -77,11 +77,11 @@ static inline size_t strlist_size(const struct strlist *list)
return list ? list->size : 0;
}
-struct strlist safe_alloc *strlist_alloc(bool uniq);
-const struct strlist_entry * never_null strlist_add(struct strlist *list, const char *str);
-const struct strlist_entry * printf_func(2, 3) never_null
+struct strlist * safe_alloc strlist_alloc(bool uniq);
+const struct strlist_entry *strlist_add(struct strlist *list, const char *str);
+const struct strlist_entry * printf_func(2, 3)
strlist_printf(struct strlist *list, const char *fmt, ...);
-const struct strlist_entry * never_null
+const struct strlist_entry *
strlist_vprintf(struct strlist *list, const char *fmt, va_list ap);
const struct strlist_entry *
strlist_find(const struct strlist *list, const char *str);
diff --git a/macros/macros.pl b/macros/macros.pl
index 9fc425d4..517a9e6f 100755
--- a/macros/macros.pl
+++ b/macros/macros.pl
@@ -276,19 +276,19 @@ print OUT " };\n";
# Put a large value in unused slots. This makes it extremely unlikely
# that any combination that involves unused slot will pass the range test.
# This speeds up rejection of unrecognized tokens, i.e. identifiers.
-print OUT "#define UNUSED (65535/3)\n";
+print OUT "#define UNUSED_HASH_ENTRY (65535/3)\n";
print OUT " static const int16_t hash1[$n] = {\n";
for ($i = 0; $i < $n; $i++) {
my $h = ${$g}[$i*2+0];
- print OUT " ", defined($h) ? $h : 'UNUSED', ",\n";
+ print OUT " ", defined($h) ? $h : 'UNUSED_HASH_ENTRY', ",\n";
}
print OUT " };\n";
print OUT " static const int16_t hash2[$n] = {\n";
for ($i = 0; $i < $n; $i++) {
my $h = ${$g}[$i*2+1];
- print OUT " ", defined($h) ? $h : 'UNUSED', ",\n";
+ print OUT " ", defined($h) ? $h : 'UNUSED_HASH_ENTRY', ",\n";
}
print OUT " };\n";
diff --git a/nasm.spec.in b/nasm.spec.in
index 35067f21..7882a02a 100644
--- a/nasm.spec.in
+++ b/nasm.spec.in
@@ -15,6 +15,7 @@ BuildRequires: automake
BuildRequires: asciidoc
BuildRequires: xmlto
BuildRequires: xz
+BuildRequires: perl
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
%package doc
@@ -47,9 +48,8 @@ include linker, library manager, loader, and information dump.
%build
sh autogen.sh
-%configure --disable-pdf-compression --enable-sections
+%configure --enable-sections
make %{?_smp_mflags} everything
-xz -9ef doc/nasmdoc.pdf
%install
rm -rf "%{buildroot}"
diff --git a/nasmlib/file.c b/nasmlib/file.c
index e5c0e335..62b854de 100644
--- a/nasmlib/file.c
+++ b/nasmlib/file.c
@@ -148,6 +148,11 @@ os_filename os_mangle_filename(const char *filename)
#endif
+void nasm_set_binary_mode(FILE *f)
+{
+ os_set_binary_mode(f);
+}
+
FILE *nasm_open_read(const char *filename, enum file_flags flags)
{
FILE *f = NULL;
@@ -210,6 +215,20 @@ FILE *nasm_open_write(const char *filename, enum file_flags flags)
nasm_fatalf(ERR_NOFILE, "unable to open output file: `%s': %s",
filename, strerror(errno));
+ switch (flags & NF_BUF_MASK) {
+ case NF_IONBF:
+ setvbuf(f, NULL, _IONBF, 0);
+ break;
+ case NF_IOLBF:
+ setvbuf(f, NULL, _IOLBF, 0);
+ break;
+ case NF_IOFBF:
+ setvbuf(f, NULL, _IOFBF, 0);
+ break;
+ default:
+ break;
+ }
+
return f;
}
diff --git a/nasmlib/file.h b/nasmlib/file.h
index 4f0420ec..fc8f893d 100644
--- a/nasmlib/file.h
+++ b/nasmlib/file.h
@@ -103,6 +103,24 @@ typedef struct _stati64 os_struct_stat;
# define os_stat _wstati64
# define os_fstat _fstati64
+/*
+ * On Win32/64, freopen() and _wfreopen() fails when the mode string
+ * is with the letter 'b' that represents to set binary mode. On
+ * POSIX operating systems, the 'b' is ignored, without failure.
+ */
+
+#include <io.h>
+#include <fcntl.h>
+
+static inline void os_set_binary_mode(FILE *f) {
+ int ret = _setmode(_fileno(f), _O_BINARY);
+
+ if (ret == -1) {
+ nasm_fatalf(ERR_NOFILE, "unable to open file: %s",
+ strerror(errno));
+ }
+}
+
#else /* not _WIN32 */
typedef const char *os_filename;
@@ -117,6 +135,10 @@ static inline void os_free_filename(os_filename filename)
(void)filename; /* Nothing to do */
}
+static inline void os_set_binary_mode(FILE *f) {
+ (void)f;
+}
+
# define os_fopen fopen
#if defined(HAVE_FACCESSAT) && defined(AT_EACCESS)
diff --git a/nasmlib/hashtbl.c b/nasmlib/hashtbl.c
index 3f4a957c..9a4c0b55 100644
--- a/nasmlib/hashtbl.c
+++ b/nasmlib/hashtbl.c
@@ -277,8 +277,9 @@ void hash_free_all(struct hash_table *head, bool free_keys)
const struct hash_node *np;
hash_for_each(head, it, np) {
- nasm_free(np->data);
- if (free_keys)
+ if (np->data)
+ nasm_free(np->data);
+ if (free_keys && np->key)
nasm_free((void *)np->key);
}
diff --git a/nasmlib/perfhash.pl b/nasmlib/perfhash.pl
index 8df21f69..9236bfec 100755
--- a/nasmlib/perfhash.pl
+++ b/nasmlib/perfhash.pl
@@ -334,18 +334,18 @@ if ($output eq 'h') {
}
print F "\n};\n\n";
- print F "#define UNUSED (65536/3)\n\n";
+ print F "#define UNUSED_HASH_ENTRY (65536/3)\n\n";
printf F "static const int16_t %s_hashvals[%d] = ", $name, $n*2;
$c = '{';
for (my $i = 0; $i < $n; $i++) {
my $h = ${$g}[$i*2+0];
- print F "$c\n ", defined($h) ? $h : 'UNUSED';
+ print F "$c\n ", defined($h) ? $h : 'UNUSED_HASH_ENTRY';
$c = ',';
}
for (my $i = 0; $i < $n; $i++) {
my $h = ${$g}[$i*2+1];
- print F "$c\n ", defined($h) ? $h : 'UNUSED';
+ print F "$c\n ", defined($h) ? $h : 'UNUSED_HASH_ENTRY';
$c = ',';
}
print F "\n};\n\n";
diff --git a/nasmlib/rbtree.c b/nasmlib/rbtree.c
index 5af6067d..8b74c0c4 100644
--- a/nasmlib/rbtree.c
+++ b/nasmlib/rbtree.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
- *
- * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ *
+ * Copyright 1996-2020 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -14,7 +14,7 @@
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
@@ -34,86 +34,202 @@
/*
* rbtree.c
*
- * Simple implementation of a left-leaning red-black tree with 64-bit
- * integer keys. The search operation will return the highest node <=
- * the key; only search and insert are supported, but additional
- * standard llrbtree operations can be coded up at will.
+ * Simple implementation of a "left-leaning threaded red-black tree"
+ * with 64-bit integer keys. The search operation will return the
+ * highest node <= the key; only search and insert are supported, but
+ * additional standard llrbtree operations can be coded up at will.
*
* See http://www.cs.princeton.edu/~rs/talks/LLRB/RedBlack.pdf for
* information about left-leaning red-black trees.
+ *
+ * The "threaded" part means that left and right pointers that would
+ * otherwise be NULL are pointers to the in-order predecessor or
+ * successor node. The only pointers that are NULL are the very left-
+ * and rightmost, for which no corresponding side node exists.
+ *
+ * This, among other things, allows for efficient predecessor and
+ * successor operations without requiring dedicated space for a parent
+ * pointer.
+ *
+ * This implementation is robust for identical key values; such keys
+ * will not have their insertion order preserved, and after insertion
+ * of unrelated keys a lookup may return a different node for the
+ * duplicated key, but the prev/next operations will always enumerate
+ * all entries.
+ *
+ * The NULL pointers at the end are considered predecessor/successor
+ * pointers, so if the corresponding flags are clear it is always safe
+ * to access the pointed-to object without an explicit NULL pointer
+ * check.
*/
#include "rbtree.h"
+#include "nasmlib.h"
-struct rbtree *rb_search(struct rbtree *tree, uint64_t key)
+struct rbtree *rb_search(const struct rbtree *tree, uint64_t key)
{
- struct rbtree *best = NULL;
-
- while (tree) {
- if (tree->key == key)
- return tree;
- else if (tree->key > key)
- tree = tree->left;
- else {
- best = tree;
- tree = tree->right;
+ const struct rbtree *best = NULL;
+
+ if (tree) {
+ while (true) {
+ if (tree->key > key) {
+ if (tree->m.flags & RBTREE_NODE_PRED)
+ break;
+ tree = tree->m.left;
+ } else {
+ best = tree;
+ if (tree->key == key || (tree->m.flags & RBTREE_NODE_SUCC))
+ break;
+ tree = tree->m.right;
+ }
}
}
- return best;
+ return (struct rbtree *)best;
+}
+
+/* Reds two left in a row? */
+static inline bool is_red_left_left(struct rbtree *h)
+{
+ return !(h->m.flags & RBTREE_NODE_PRED) &&
+ !(h->m.left->m.flags & (RBTREE_NODE_BLACK|RBTREE_NODE_PRED)) &&
+ !(h->m.left->m.left->m.flags & RBTREE_NODE_BLACK);
}
-static bool is_red(struct rbtree *h)
+/* Node to the right is red? */
+static inline bool is_red_right(struct rbtree *h)
{
- return h && h->red;
+ return !(h->m.flags & RBTREE_NODE_SUCC) &&
+ !(h->m.right->m.flags & RBTREE_NODE_BLACK);
}
-static struct rbtree *rotate_left(struct rbtree *h)
+/* Both the left and right hand nodes are red? */
+static inline bool is_red_both(struct rbtree *h)
{
- struct rbtree *x = h->right;
- h->right = x->left;
- x->left = h;
- x->red = x->left->red;
- x->left->red = true;
+ return !(h->m.flags & (RBTREE_NODE_PRED|RBTREE_NODE_SUCC))
+ && !(h->m.left->m.flags & h->m.right->m.flags & RBTREE_NODE_BLACK);
+}
+
+static inline struct rbtree *rotate_left(struct rbtree *h)
+{
+ struct rbtree *x = h->m.right;
+ enum rbtree_node_flags hf = h->m.flags;
+ enum rbtree_node_flags xf = x->m.flags;
+
+ if (xf & RBTREE_NODE_PRED) {
+ h->m.right = x;
+ h->m.flags = (hf & RBTREE_NODE_PRED) | RBTREE_NODE_SUCC;
+ } else {
+ h->m.right = x->m.left;
+ h->m.flags = hf & RBTREE_NODE_PRED;
+ }
+ x->m.flags = (hf & RBTREE_NODE_BLACK) | (xf & RBTREE_NODE_SUCC);
+ x->m.left = h;
+
return x;
}
-static struct rbtree *rotate_right(struct rbtree *h)
+static inline struct rbtree *rotate_right(struct rbtree *h)
{
- struct rbtree *x = h->left;
- h->left = x->right;
- x->right = h;
- x->red = x->right->red;
- x->right->red = true;
+ struct rbtree *x = h->m.left;
+ enum rbtree_node_flags hf = h->m.flags;
+ enum rbtree_node_flags xf = x->m.flags;
+
+ if (xf & RBTREE_NODE_SUCC) {
+ h->m.left = x;
+ h->m.flags = (hf & RBTREE_NODE_SUCC) | RBTREE_NODE_PRED;
+ } else {
+ h->m.left = x->m.right;
+ h->m.flags = hf & RBTREE_NODE_SUCC;
+ }
+ x->m.flags = (hf & RBTREE_NODE_BLACK) | (xf & RBTREE_NODE_PRED);
+ x->m.right = h;
+
return x;
}
-static void color_flip(struct rbtree *h)
+static inline void color_flip(struct rbtree *h)
{
- h->red = !h->red;
- h->left->red = !h->left->red;
- h->right->red = !h->right->red;
+ h->m.flags ^= RBTREE_NODE_BLACK;
+ h->m.left->m.flags ^= RBTREE_NODE_BLACK;
+ h->m.right->m.flags ^= RBTREE_NODE_BLACK;
}
+static struct rbtree *
+_rb_insert(struct rbtree *tree, struct rbtree *node);
+
struct rbtree *rb_insert(struct rbtree *tree, struct rbtree *node)
{
- if (!tree) {
- node->red = true;
- return node;
- }
+ /* Initialize node as if it was the sole member of the tree */
+
+ nasm_zero(node->m);
+ node->m.flags = RBTREE_NODE_PRED|RBTREE_NODE_SUCC;
+
+ if (unlikely(!tree))
+ return node;
+
+ return _rb_insert(tree, node);
+}
- if (is_red(tree->left) && is_red(tree->right))
+static struct rbtree *
+_rb_insert(struct rbtree *tree, struct rbtree *node)
+{
+ /* Recursive part of the algorithm */
+
+ /* Red on both sides? */
+ if (is_red_both(tree))
color_flip(tree);
- if (node->key < tree->key)
- tree->left = rb_insert(tree->left, node);
- else
- tree->right = rb_insert(tree->right, node);
+ if (node->key < tree->key) {
+ node->m.right = tree; /* Potential successor */
+ if (tree->m.flags & RBTREE_NODE_PRED) {
+ node->m.left = tree->m.left;
+ tree->m.flags &= ~RBTREE_NODE_PRED;
+ tree->m.left = node;
+ } else {
+ tree->m.left = _rb_insert(tree->m.left, node);
+ }
+ } else {
+ node->m.left = tree; /* Potential predecessor */
+ if (tree->m.flags & RBTREE_NODE_SUCC) {
+ node->m.right = tree->m.right;
+ tree->m.flags &= ~RBTREE_NODE_SUCC;
+ tree->m.right = node;
+ } else {
+ tree->m.right = _rb_insert(tree->m.right, node);
+ }
+ }
- if (is_red(tree->right))
+ if (is_red_right(tree))
tree = rotate_left(tree);
- if (is_red(tree->left) && is_red(tree->left->left))
+ if (is_red_left_left(tree))
tree = rotate_right(tree);
return tree;
}
+
+struct rbtree *rb_prev(const struct rbtree *node)
+{
+ struct rbtree *np = node->m.left;
+
+ if (node->m.flags & RBTREE_NODE_PRED)
+ return np;
+
+ while (!(np->m.flags & RBTREE_NODE_SUCC))
+ np = np->m.right;
+
+ return np;
+}
+
+struct rbtree *rb_next(const struct rbtree *node)
+{
+ struct rbtree *np = node->m.right;
+
+ if (node->m.flags & RBTREE_NODE_SUCC)
+ return np;
+
+ while (!(np->m.flags & RBTREE_NODE_PRED))
+ np = np->m.left;
+
+ return np;
+}
diff --git a/nasmlib/rlimit.c b/nasmlib/rlimit.c
new file mode 100644
index 00000000..096879f8
--- /dev/null
+++ b/nasmlib/rlimit.c
@@ -0,0 +1,78 @@
+ /* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2020 The NASM Authors - All Rights Reserved
+ * See the file AUTHORS included with the NASM distribution for
+ * the specific copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include "compiler.h"
+#include "nasmlib.h"
+
+#ifdef HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
+#endif
+
+#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_STACK)
+
+size_t nasm_get_stack_size_limit(void)
+{
+ struct rlimit rl;
+
+ if (getrlimit(RLIMIT_STACK, &rl))
+ return SIZE_MAX;
+
+# ifdef RLIM_SAVED_MAX
+ if (rl.rlim_cur == RLIM_SAVED_MAX)
+ rl.rlim_cur = rl.rlim_max;
+# endif
+
+ if (
+# ifdef RLIM_INFINITY
+ rl.rlim_cur >= RLIM_INFINITY ||
+# endif
+# ifdef RLIM_SAVED_CUR
+ rl.rlim_cur == RLIM_SAVED_CUR ||
+# endif
+# ifdef RLIM_SAVED_MAX
+ rl.rlim_cur == RLIM_SAVED_MAX ||
+# endif
+ (size_t)rl.rlim_cur != rl.rlim_cur)
+ return SIZE_MAX;
+
+ return rl.rlim_cur;
+}
+
+#else
+
+size_t nasm_get_stack_size_limit(void)
+{
+ return SIZE_MAX;
+}
+
+#endif
diff --git a/nasmlib/strlist.c b/nasmlib/strlist.c
index db5a09ab..449304b7 100644
--- a/nasmlib/strlist.c
+++ b/nasmlib/strlist.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2018 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2020 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -102,7 +102,8 @@ strlist_add(struct strlist *list, const char *str)
const struct strlist_entry *
strlist_vprintf(struct strlist *list, const char *fmt, va_list ap)
{
- struct strlist_entry *e;
+ /* clang miscompiles offsetin() unless e is initialized here */
+ struct strlist_entry *e = NULL;
struct hash_insert hi;
if (!list)
diff --git a/output/codeview.c b/output/codeview.c
index 4dbc9b3a..be3fd27a 100644
--- a/output/codeview.c
+++ b/output/codeview.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2017 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2020 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -609,9 +609,9 @@ static void write_linenumber_table(struct coff_Section *const sect)
}
}
-static uint16_t write_symbolinfo_obj(struct coff_Section *sect)
+static uint32_t write_symbolinfo_obj(struct coff_Section *sect)
{
- uint16_t obj_len;
+ uint32_t obj_len;
obj_len = 2 + 4 + cv8_state.outfile.namebytes;
@@ -623,11 +623,11 @@ static uint16_t write_symbolinfo_obj(struct coff_Section *sect)
return obj_len;
}
-static uint16_t write_symbolinfo_properties(struct coff_Section *sect,
+static uint32_t write_symbolinfo_properties(struct coff_Section *sect,
const char *const creator_str)
{
/* https://github.com/Microsoft/microsoft-pdb/blob/1d60e041/include/cvinfo.h#L3313 */
- uint16_t creator_len;
+ uint32_t creator_len;
creator_len = 2 + 4 + 2 + 3*2 + 3*2 + strlen(creator_str)+1 + 2;
@@ -671,9 +671,9 @@ static uint16_t write_symbolinfo_properties(struct coff_Section *sect,
return creator_len;
}
-static uint16_t write_symbolinfo_symbols(struct coff_Section *sect)
+static uint32_t write_symbolinfo_symbols(struct coff_Section *sect)
{
- uint16_t len = 0, field_len;
+ uint32_t len = 0, field_len;
uint32_t field_base;
struct cv8_symbol *sym;
@@ -727,7 +727,7 @@ static uint16_t write_symbolinfo_symbols(struct coff_Section *sect)
static void write_symbolinfo_table(struct coff_Section *const sect)
{
static const char creator_str[] = "The Netwide Assembler " NASM_VER;
- uint16_t obj_length, creator_length, sym_length;
+ uint32_t obj_length, creator_length, sym_length;
uint32_t field_length = 0, out_len;
nasm_assert(cv8_state.outfile.namebytes);
@@ -791,32 +791,28 @@ static void build_symbol_table(struct coff_Section *const sect)
static void build_type_table(struct coff_Section *const sect)
{
- uint16_t field_len;
- struct cv8_symbol *sym;
+ uint32_t field_len;
+ uint32_t typeindex = 0x1000;
+ uint32_t idx_arglist;
section_write32(sect, 0x00000004);
- saa_rewind(cv8_state.symbols);
- while ((sym = saa_rstruct(cv8_state.symbols))) {
- if (sym->type != SYMTYPE_PROC)
- continue;
-
- /* proc leaf */
-
- field_len = 2 + 4 + 4 + 4 + 2;
- section_write16(sect, field_len);
- section_write16(sect, 0x1008); /* PROC type */
-
- section_write32(sect, 0x00000003); /* return type */
- section_write32(sect, 0); /* calling convention (default) */
- section_write32(sect, sym->typeindex);
- section_write16(sect, 0); /* # params */
-
- /* arglist */
-
- field_len = 2 + 4;
- section_write16(sect, field_len);
- section_write16(sect, 0x1201); /* ARGLIST */
- section_write32(sect, 0); /*num params */
- }
+ /* empty argument list type */
+ field_len = 2 + 4;
+ section_write16(sect, field_len);
+ section_write16(sect, 0x1201); /* ARGLIST */
+ section_write32(sect, 0); /* num params */
+ idx_arglist = typeindex++;
+
+ /* procedure type: void proc(void) */
+ field_len = 2 + 4 + 1 + 1 + 2 + 4;
+ section_write16(sect, field_len);
+ section_write16(sect, 0x1008); /* PROC type */
+
+ section_write32(sect, 0x00000003); /* return type VOID */
+ section_write8(sect, 0); /* calling convention (default) */
+ section_write8(sect, 0); /* function attributes */
+ section_write16(sect, 0); /* # params */
+ section_write32(sect, idx_arglist); /* argument list type */
+ /* idx_voidfunc = typeindex++; */
}
diff --git a/output/outelf.c b/output/outelf.c
index 4976b680..61af0208 100644
--- a/output/outelf.c
+++ b/output/outelf.c
@@ -176,7 +176,32 @@ static void stabs_generate(void);
static void stabs_cleanup(void);
/* dwarf debugging routines */
-static void dwarf_init(void);
+
+/* This should match the order in elf_write() */
+enum dwarf_sect {
+ DWARF_ARANGES,
+ DWARF_RELA_ARANGES,
+ DWARF_PUBNAMES,
+ DWARF_INFO,
+ DWARF_RELA_INFO,
+ DWARF_ABBREV,
+ DWARF_LINE,
+ DWARF_RELA_LINE,
+ DWARF_FRAME,
+ DWARF_LOC,
+ DWARF_NSECT
+};
+
+struct dwarf_format {
+ uint16_t dwarf_version;
+ uint16_t sect_version[DWARF_NSECT];
+ /* ... add more here to generalize further */
+};
+const struct dwarf_format *dwfmt;
+
+static void dwarf32_init(void);
+static void dwarfx32_init(void);
+static void dwarf64_init(void);
static void dwarf_linenum(const char *filename, int32_t linenumber, int32_t);
static void dwarf_output(int, void *);
static void dwarf_generate(void);
@@ -1108,7 +1133,8 @@ static void elf32_out(int32_t segto, const void *data,
/* again some stabs debugging stuff */
sinfo.offset = s->len;
- sinfo.section = s->shndx;
+ /* Adjust to an index of the section table. */
+ sinfo.section = s->shndx - 1;
sinfo.segto = segto;
sinfo.name = s->name;
dfmt->debug_output(TY_DEBUGSYMLIN, &sinfo);
@@ -1312,7 +1338,8 @@ static void elf64_out(int32_t segto, const void *data,
/* again some stabs debugging stuff */
sinfo.offset = s->len;
- sinfo.section = s->shndx;
+ /* Adjust to an index of the section table. */
+ sinfo.section = s->shndx - 1;
sinfo.segto = segto;
sinfo.name = s->name;
dfmt->debug_output(TY_DEBUGSYMLIN, &sinfo);
@@ -1592,7 +1619,8 @@ static void elfx32_out(int32_t segto, const void *data,
/* again some stabs debugging stuff */
sinfo.offset = s->len;
- sinfo.section = s->shndx;
+ /* Adjust to an index of the section table. */
+ sinfo.section = s->shndx - 1;
sinfo.segto = segto;
sinfo.name = s->name;
dfmt->debug_output(TY_DEBUGSYMLIN, &sinfo);
@@ -2404,7 +2432,7 @@ static const struct pragma_facility elf_pragma_list[] =
static const struct dfmt elf32_df_dwarf = {
"ELF32 (i386) dwarf (newer)",
"dwarf",
- dwarf_init,
+ dwarf32_init,
dwarf_linenum,
null_debug_deflabel,
null_debug_directive,
@@ -2456,7 +2484,7 @@ const struct ofmt of_elf32 = {
static const struct dfmt elf64_df_dwarf = {
"ELF64 (x86-64) dwarf (newer)",
"dwarf",
- dwarf_init,
+ dwarf64_init,
dwarf_linenum,
null_debug_deflabel,
null_debug_directive,
@@ -2508,7 +2536,7 @@ const struct ofmt of_elf64 = {
static const struct dfmt elfx32_df_dwarf = {
"ELFx32 (x86-64) dwarf (newer)",
"dwarf",
- dwarf_init,
+ dwarfx32_init,
dwarf_linenum,
null_debug_deflabel,
null_debug_directive,
@@ -2936,11 +2964,69 @@ static void stabs_cleanup(void)
/* dwarf routines */
-static void dwarf_init(void)
+static void dwarf_init_common(const struct dwarf_format *fmt)
{
+ dwfmt = fmt;
ndebugs = 3; /* 3 debug symbols */
}
+static void dwarf32_init(void)
+{
+ static const struct dwarf_format dwfmt32 = {
+ 2, /* DWARF 2 */
+ /* section version numbers: */
+ { 2, /* .debug_aranges */
+ 0, /* .rela.debug_aranges */
+ 2, /* .debug_pubnames */
+ 2, /* .debug_info */
+ 0, /* .rela.debug_info */
+ 0, /* .debug_abbrev */
+ 2, /* .debug_line */
+ 0, /* .rela.debug_line */
+ 1, /* .debug_frame */
+ 0 } /* .debug_loc */
+ };
+ dwarf_init_common(&dwfmt32);
+}
+
+static void dwarfx32_init(void)
+{
+ static const struct dwarf_format dwfmtx32 = {
+ 3, /* DWARF 3 */
+ /* section version numbers: */
+ { 2, /* .debug_aranges */
+ 0, /* .rela.debug_aranges */
+ 2, /* .debug_pubnames */
+ 3, /* .debug_info */
+ 0, /* .rela.debug_info */
+ 0, /* .debug_abbrev */
+ 3, /* .debug_line */
+ 0, /* .rela.debug_line */
+ 3, /* .debug_frame */
+ 0 } /* .debug_loc */
+ };
+ dwarf_init_common(&dwfmtx32);
+}
+
+static void dwarf64_init(void)
+{
+ static const struct dwarf_format dwfmt64 = {
+ 3, /* DWARF 3 */
+ /* section version numbers: */
+ { 2, /* .debug_aranges */
+ 0, /* .rela.debug_aranges */
+ 2, /* .debug_pubnames */
+ 3, /* .debug_info */
+ 0, /* .rela.debug_info */
+ 0, /* .debug_abbrev */
+ 3, /* .debug_line */
+ 0, /* .rela.debug_line */
+ 3, /* .debug_frame */
+ 0 } /* .debug_loc */
+ };
+ dwarf_init_common(&dwfmt64);
+}
+
static void dwarf_linenum(const char *filename, int32_t linenumber,
int32_t segto)
{
@@ -3023,7 +3109,7 @@ static void dwarf_generate(void)
/* and build aranges section */
paranges = saa_init(1L);
parangesrel = saa_init(1L);
- saa_write16(paranges,2); /* dwarf version */
+ saa_write16(paranges, dwfmt->sect_version[DWARF_ARANGES]);
saa_write32(parangesrel, paranges->datalen+4);
saa_write32(parangesrel, (dwarf_infosym << 8) + R_386_32); /* reloc to info */
saa_write32(parangesrel, 0);
@@ -3068,7 +3154,7 @@ static void dwarf_generate(void)
/* and build aranges section */
paranges = saa_init(1L);
parangesrel = saa_init(1L);
- saa_write16(paranges,3); /* dwarf version */
+ saa_write16(paranges, dwfmt->sect_version[DWARF_ARANGES]);
saa_write32(parangesrel, paranges->datalen+4);
saa_write32(parangesrel, (dwarf_infosym << 8) + R_X86_64_32); /* reloc to info */
saa_write32(parangesrel, 0);
@@ -3114,7 +3200,7 @@ static void dwarf_generate(void)
/* and build aranges section */
paranges = saa_init(1L);
parangesrel = saa_init(1L);
- saa_write16(paranges,3); /* dwarf version */
+ saa_write16(paranges, dwfmt->sect_version[DWARF_ARANGES]);
saa_write64(parangesrel, paranges->datalen+4);
saa_write64(parangesrel, (dwarf_infosym << 32) + R_X86_64_32); /* reloc to info */
saa_write64(parangesrel, 0);
@@ -3163,23 +3249,28 @@ static void dwarf_generate(void)
saa_free(parangesrel);
/* build pubnames section */
- ppubnames = saa_init(1L);
- saa_write16(ppubnames,3); /* dwarf version */
- saa_write32(ppubnames,0); /* offset into info */
- saa_write32(ppubnames,0); /* space used in info */
- saa_write32(ppubnames,0); /* end of list */
- saalen = ppubnames->datalen;
- pubnameslen = saalen + 4;
- pubnamesbuf = pbuf = nasm_malloc(pubnameslen);
- WRITELONG(pbuf,saalen); /* initial length */
- saa_rnbytes(ppubnames, pbuf, saalen);
- saa_free(ppubnames);
+ if (0) {
+ ppubnames = saa_init(1L);
+ saa_write16(ppubnames,dwfmt->sect_version[DWARF_PUBNAMES]);
+ saa_write32(ppubnames,0); /* offset into info */
+ saa_write32(ppubnames,0); /* space used in info */
+ saa_write32(ppubnames,0); /* end of list */
+ saalen = ppubnames->datalen;
+ pubnameslen = saalen + 4;
+ pubnamesbuf = pbuf = nasm_malloc(pubnameslen);
+ WRITELONG(pbuf,saalen); /* initial length */
+ saa_rnbytes(ppubnames, pbuf, saalen);
+ saa_free(ppubnames);
+ } else {
+ /* Don't write a section without actual information */
+ pubnameslen = 0;
+ }
if (is_elf32()) {
/* build info section */
pinfo = saa_init(1L);
pinforel = saa_init(1L);
- saa_write16(pinfo,2); /* dwarf version */
+ saa_write16(pinfo, dwfmt->sect_version[DWARF_INFO]);
saa_write32(pinforel, pinfo->datalen + 4);
saa_write32(pinforel, (dwarf_abbrevsym << 8) + R_386_32); /* reloc to abbrev */
saa_write32(pinforel, 0);
@@ -3218,7 +3309,7 @@ static void dwarf_generate(void)
/* build info section */
pinfo = saa_init(1L);
pinforel = saa_init(1L);
- saa_write16(pinfo,3); /* dwarf version */
+ saa_write16(pinfo, dwfmt->sect_version[DWARF_INFO]);
saa_write32(pinforel, pinfo->datalen + 4);
saa_write32(pinforel, (dwarf_abbrevsym << 8) + R_X86_64_32); /* reloc to abbrev */
saa_write32(pinforel, 0);
@@ -3258,7 +3349,7 @@ static void dwarf_generate(void)
/* build info section */
pinfo = saa_init(1L);
pinforel = saa_init(1L);
- saa_write16(pinfo,3); /* dwarf version */
+ saa_write16(pinfo, dwfmt->sect_version[DWARF_INFO]);
saa_write64(pinforel, pinfo->datalen + 4);
saa_write64(pinforel, (dwarf_abbrevsym << 32) + R_X86_64_32); /* reloc to abbrev */
saa_write64(pinforel, 0);
@@ -3373,7 +3464,7 @@ static void dwarf_generate(void)
linelen = linepoff + totlen + 10;
linebuf = pbuf = nasm_malloc(linelen);
WRITELONG(pbuf,linelen-4); /* initial length */
- WRITESHORT(pbuf,3); /* dwarf version */
+ WRITESHORT(pbuf,dwfmt->sect_version[DWARF_LINE]);
WRITELONG(pbuf,linepoff); /* offset to line number program */
/* write line header */
saalen = linepoff;
@@ -3435,24 +3526,31 @@ static void dwarf_generate(void)
saa_rnbytes(plinesrel, pbuf, saalen);
saa_free(plinesrel);
- /* build frame section */
- framelen = 4;
- framebuf = pbuf = nasm_malloc(framelen);
- WRITELONG(pbuf,framelen-4); /* initial length */
+ /* build .debug_frame section */
+ if (0) {
+ framelen = 4;
+ framebuf = pbuf = nasm_malloc(framelen);
+ WRITELONG(pbuf,framelen-4); /* initial length */
+ } else {
+ /* Leave .debug_frame empty if not used! */
+ framelen = 0;
+ }
- /* build loc section */
- loclen = 16;
- locbuf = pbuf = nasm_malloc(loclen);
- if (is_elf32()) {
- WRITELONG(pbuf,0); /* null beginning offset */
- WRITELONG(pbuf,0); /* null ending offset */
- } else if (is_elfx32()) {
- WRITELONG(pbuf,0); /* null beginning offset */
- WRITELONG(pbuf,0); /* null ending offset */
+ /* build .debug_loc section */
+ if (0) {
+ loclen = 16;
+ locbuf = pbuf = nasm_malloc(loclen);
+ if (is_elf32() || is_elfx32()) {
+ WRITELONG(pbuf,0); /* null beginning offset */
+ WRITELONG(pbuf,0); /* null ending offset */
+ } else {
+ nasm_assert(is_elf64());
+ WRITEDLONG(pbuf,0); /* null beginning offset */
+ WRITEDLONG(pbuf,0); /* null ending offset */
+ }
} else {
- nasm_assert(is_elf64());
- WRITEDLONG(pbuf,0); /* null beginning offset */
- WRITEDLONG(pbuf,0); /* null ending offset */
+ /* Leave .debug_frame empty if not used! */
+ loclen = 0;
}
}
diff --git a/output/outlib.c b/output/outlib.c
index c60de055..54c87530 100644
--- a/output/outlib.c
+++ b/output/outlib.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
- *
- * Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ *
+ * Copyright 1996-2020 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -14,7 +14,7 @@
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
@@ -32,14 +32,13 @@
* ----------------------------------------------------------------------- */
/*
- * libout.c
+ * outlib.c
*
* Common routines for the output backends.
*/
-#include "compiler.h"
-#include "nasm.h"
#include "outlib.h"
+#include "raa.h"
uint64_t realsize(enum out_type type, uint64_t size)
{
@@ -56,3 +55,270 @@ uint64_t realsize(enum out_type type, uint64_t size)
return size;
}
}
+
+/* Common section/symbol handling */
+
+struct ol_sect *_ol_sect_list;
+uint64_t _ol_nsects; /* True sections, not external symbols */
+static struct ol_sect **ol_sect_tail = &_ol_sect_list;
+static struct hash_table ol_secthash;
+static struct RAA *ol_sect_index_tbl;
+
+struct ol_sym *_ol_sym_list;
+uint64_t _ol_nsyms;
+static struct ol_sym **ol_sym_tail = &_ol_sym_list;
+static struct hash_table ol_symhash;
+
+void ol_init(void)
+{
+}
+
+static void ol_free_symbols(void)
+{
+ struct ol_sym *s, *stmp;
+
+ hash_free(&ol_symhash);
+
+ list_for_each_safe(s, stmp, _ol_sym_list) {
+ nasm_free((char *)s->name);
+ nasm_free(s);
+ }
+
+ _ol_nsyms = 0;
+ _ol_sym_list = NULL;
+ ol_sym_tail = &_ol_sym_list;
+}
+
+static void ol_free_sections(void)
+{
+ struct ol_sect *s, *stmp;
+
+ hash_free(&ol_secthash);
+ raa_free(ol_sect_index_tbl);
+ ol_sect_index_tbl = NULL;
+
+ list_for_each_safe(s, stmp, _ol_sect_list) {
+ saa_free(s->data);
+ saa_free(s->reloc);
+ nasm_free((char *)s->name);
+ nasm_free(s);
+ }
+
+ _ol_nsects = 0;
+ _ol_sect_list = NULL;
+ ol_sect_tail = &_ol_sect_list;
+}
+
+void ol_cleanup(void)
+{
+ ol_free_symbols();
+ ol_free_sections();
+}
+
+/*
+ * Allocate a section index and add a section, subsection, or external
+ * symbol to the section-by-index table. If the index provided is zero,
+ * allocate a new index via seg_alloc().
+ */
+static uint32_t ol_seg_alloc(void *s, uint32_t ix)
+{
+ if (!ix)
+ ix = seg_alloc();
+ ol_sect_index_tbl = raa_write_ptr(ol_sect_index_tbl, ix >> 1, s);
+ return ix;
+}
+
+/*
+ * Find a section or create a new section structure if it does not exist
+ * and allocate it an index value via seg_alloc().
+ */
+struct ol_sect *_ol_get_sect(const char *name, size_t ssize, size_t rsize)
+{
+ struct ol_sect *s, **sp;
+ struct hash_insert hi;
+
+ sp = (struct ol_sect **)hash_find(&ol_secthash, name, &hi);
+ if (sp)
+ return *sp;
+
+ s = nasm_zalloc(ssize);
+ s->syml.tail = &s->syml.head;
+ s->name = nasm_strdup(name);
+ s->data = saa_init(1);
+ s->reloc = saa_init(rsize);
+ *ol_sect_tail = s;
+ ol_sect_tail = &s->next;
+ _ol_nsects++;
+ s->index = s->subindex = ol_seg_alloc(s, 0);
+
+ hash_add(&hi, s->name, s);
+ return s;
+}
+
+/* Find a section by name without creating one */
+struct ol_sect *_ol_sect_by_name(const char *name)
+{
+ struct ol_sect **sp;
+
+ sp = (struct ol_sect **)hash_find(&ol_secthash, name, NULL);
+ return sp ? *sp : NULL;
+}
+
+/* Find a section or external symbol by index; NULL if not valid */
+struct ol_sect *_ol_sect_by_index(int32_t index)
+{
+ uint32_t ix = index;
+
+ if (unlikely(ix >= SEG_ABS))
+ return NULL;
+
+ return raa_read_ptr(ol_sect_index_tbl, ix >> 1);
+}
+
+/*
+ * Start a new subsection for the given section. At the moment, once a
+ * subsection has been created, it is not possible to revert to an
+ * earlier subsection. ol_sect_by_index() will return the main section
+ * structure. Returns the new section index. This is used to prevent
+ * the front end from optimizing across subsection boundaries.
+ */
+int32_t _ol_new_subsection(struct ol_sect *sect)
+{
+ if (unlikely(!sect))
+ return NO_SEG;
+
+ return sect->subindex = ol_seg_alloc(sect, 0);
+}
+
+/*
+ * Insert a symbol into a list; need to use upcasting using container_of()
+ * to walk the list later.
+ */
+static void ol_add_sym_to(struct ol_symlist *syml, struct ol_symhead *head,
+ uint64_t offset)
+{
+ syml->tree.key = offset;
+ head->tree = rb_insert(head->tree, &syml->tree);
+ *head->tail = syml;
+ head->tail = &syml->next;
+ head->n++;
+}
+
+/*
+ * Create a location structure from seg:offs
+ */
+void ol_mkloc(struct ol_loc *loc, int64_t offs, int32_t seg)
+{
+ nasm_zero(*loc);
+ loc->offs = offs;
+
+ if (unlikely((uint32_t)seg >= SEG_ABS)) {
+ if (likely(seg == NO_SEG)) {
+ loc->seg.t = OS_NOSEG;
+ } else {
+ loc->seg.t = OS_ABS;
+ loc->seg.index = seg - SEG_ABS;
+ }
+ } else {
+ loc->seg.index = seg & ~1;
+ loc->seg.t = OS_SECT | (seg & 1);
+ loc->seg.s.sect = _ol_sect_by_index(loc->seg.index);
+ }
+}
+
+/*
+ * Create a new symbol. If this symbol is OS_OFFS, add it to the relevant
+ * section, too. If the symbol already exists, return NULL; this is
+ * different from ol_get_section() as a single section may be invoked
+ * many times. On the contrary, the front end will prevent a single symbol
+ * from being defined more than once.
+ *
+ * If flags has OF_GLOBAL set, add it to the global symbol hash for
+ * the containing section if applicable.
+ *
+ * If flags has OF_IMPSEC set, allocate a segment index for it via
+ * seg_alloc() unless v->index is already set, and add it to the
+ * section by index list.
+ */
+struct ol_sym *_ol_new_sym(const char *name, const struct ol_loc *v,
+ uint32_t flags, size_t size)
+{
+ struct hash_insert hi;
+ struct ol_sym *sym;
+
+ if (hash_find(&ol_symhash, name, &hi))
+ return NULL; /* Symbol already exists */
+
+ flags |= OF_SYMBOL;
+
+ sym = nasm_zalloc(size);
+ sym->name = nasm_strdup(name);
+ sym->v = *v;
+
+ if (sym->v.seg.t & OS_SECT) {
+ struct ol_sect *sect = sym->v.seg.s.sect;
+
+ if (!sect || (sect->flags & OF_SYMBOL))
+ /* Must be an external or common reference */
+ flags |= OF_IMPSEC;
+
+ if (flags & OF_IMPSEC) {
+ /* Metasection */
+ if (!sym->v.seg.s.sym) {
+ sym->v.seg.s.sym = sym;
+ sym->v.seg.index = ol_seg_alloc(sym, sym->v.seg.index);
+ }
+ } else if (sym->v.seg.t == OS_OFFS) {
+ struct ol_sect * const sect = sym->v.seg.s.sect;
+ const uint64_t offs = sym->v.offs;
+
+ ol_add_sym_to(&sym->syml, &sect->syml, offs);
+ if (flags & OF_GLOBAL)
+ ol_add_sym_to(&sym->symg, &sect->symg, offs);
+ }
+ }
+ sym->flags = flags;
+
+ *ol_sym_tail = sym;
+ ol_sym_tail = &sym->next;
+ _ol_nsyms++;
+
+ hash_add(&hi, sym->name, sym);
+ return sym;
+}
+
+/* Find a symbol in the global namespace */
+struct ol_sym *_ol_sym_by_name(const char *name)
+{
+ struct ol_sym **symp;
+
+ symp = (struct ol_sym **)hash_find(&ol_symhash, name, NULL);
+ return symp ? *symp : NULL;
+}
+
+/*
+ * Find a symbol by address in a specific section. If no symbol is defined
+ * at that exact address, return the immediately previously defined one.
+ * If global is set, then only return global symbols.
+ */
+struct ol_sym *_ol_sym_by_address(struct ol_sect *sect, int64_t addr,
+ bool global)
+{
+ struct ol_symhead *head;
+ size_t t_offs;
+ struct rbtree *t;
+
+ if (global) {
+ head = &sect->symg;
+ t_offs = offsetof(struct ol_sym, symg.tree);
+ } else {
+ head = &sect->syml;
+ t_offs = offsetof(struct ol_sym, syml.tree);
+ }
+
+ t = rb_search(head->tree, addr);
+ if (!t)
+ return NULL;
+
+ return (struct ol_sym *)((char *)t - t_offs);
+}
diff --git a/output/outlib.h b/output/outlib.h
index 30f2c0b2..7f6a7893 100644
--- a/output/outlib.h
+++ b/output/outlib.h
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2018 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2020 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -34,8 +34,12 @@
#ifndef NASM_OUTLIB_H
#define NASM_OUTLIB_H
+#include "compiler.h"
#include "nasm.h"
#include "error.h"
+#include "hashtbl.h"
+#include "saa.h"
+#include "rbtree.h"
uint64_t realsize(enum out_type type, uint64_t size);
@@ -61,5 +65,249 @@ extern const struct dfmt * const null_debug_arr[2];
/* Wrapper for unported backends */
void nasm_do_legacy_output(const struct out_data *data);
-#endif /* NASM_OUTLIB_H */
+/*
+ * Common routines for tasks that really should migrate into the core.
+ * This provides a common interface for maintaining sections and symbols,
+ * and provide quick lookups as well as declared-order sequential walks.
+ *
+ * These structures are intended to be embedded at the *top* of a
+ * backend-specific structure containing additional information.
+ *
+ * The tokens O_Section, O_Symbol and O_Reloc are intended to be
+ * defined as macros by the backend before including this file!
+ */
+
+struct ol_sect;
+struct ol_sym;
+
+#ifndef O_Section
+typedef struct ol_sect O_Section;
+#endif
+#ifndef O_Symbol
+typedef struct ol_sym O_Symbol;
+#endif
+#ifndef O_Reloc
+typedef void * O_Reloc;
+#endif
+
+/* Common section structure */
+
+/*
+ * Common flags for sections and symbols; low values reserved for
+ * backend. Note that both ol_sect and ol_sym begin with a flags
+ * field, so if a section pointer points to an external symbol instead
+ * they can be trivially resolved.
+ */
+#define OF_SYMBOL 0x80000000
+#define OF_GLOBAL 0x40000000
+#define OF_IMPSEC 0x20000000
+#define OF_COMMON 0x10000000
+
+struct ol_sym;
+
+struct ol_symlist {
+ struct ol_symlist *next;
+ struct rbtree tree;
+};
+struct ol_symhead {
+ struct ol_symlist *head, **tail;
+ struct rbtree *tree;
+ uint64_t n;
+};
+
+struct ol_sect {
+ uint32_t flags; /* Section/symbol flags */
+ struct ol_sect *next; /* Next section in declared order */
+ const char *name; /* Name of section */
+ struct ol_symhead syml; /* All symbols in this section */
+ struct ol_symhead symg; /* Global symbols in this section */
+ struct SAA *data; /* Contents of section */
+ struct SAA *reloc; /* Section relocations */
+ uint32_t index; /* Primary section index */
+ uint32_t subindex; /* Current subsection index */
+};
+
+/* Segment reference */
+enum ol_seg_type {
+ OS_NOSEG = 0, /* Plain number (no segment) */
+ OS_SEGREF = 1, /* It is a segment reference */
+ OS_ABS = 1, /* Absolute segment reference */
+ OS_SECT = 2, /* It is a real section */
+ OS_OFFS = OS_SECT, /* Offset reference in section */
+ OS_SEG = OS_SECT|OS_SEGREF /* Section reference */
+};
+
+union ol_segval {
+ struct ol_sect *sect; /* Section structure */
+ struct ol_sym *sym; /* External symbol structure */
+};
+
+struct ol_seg {
+ union ol_segval s;
+ enum ol_seg_type t;
+
+ /*
+ * For a section: subsection index
+ * For a metasymbol: virtual segment index
+ * For an absolute symbol: absolute value
+ */
+ uint32_t index;
+};
+
+/* seg:offs representing the full location value and type */
+struct ol_loc {
+ int64_t offs;
+ struct ol_seg seg;
+};
+
+/* Common symbol structure */
+struct ol_sym {
+ uint32_t flags; /* Section/symbol flags */
+ uint32_t size; /* Size value (for backend) */
+ struct ol_sym *next; /* Next symbol in declared order */
+ const char *name; /* Symbol name */
+ struct ol_symlist syml; /* Section-local symbol list */
+ struct ol_symlist symg; /* Section-local global symbol list */
+ struct ol_loc p; /* Symbol position ("where") */
+ struct ol_loc v; /* Symbol value ("what") */
+};
+
+/*
+ * Operations
+ */
+void ol_init(void);
+void ol_cleanup(void);
+/* Convert offs:seg to a location structure */
+extern void
+ol_mkloc(struct ol_loc *loc, int64_t offs, int32_t seg);
+
+/* Get the section or external symbol from a struct ol_seg */
+static inline O_Section *seg_sect(struct ol_seg *seg)
+{
+ return (O_Section *)seg->s.sect;
+}
+static inline O_Symbol *seg_xsym(struct ol_seg *seg)
+{
+ return (O_Symbol *)seg->s.sym;
+}
+
+/*
+ * Return a pointer to the symbol structure if and only if a section is
+ * really a symbol of some kind (extern, common...)
+ */
+static inline struct ol_sym *_seg_extsym(struct ol_sect *sect)
+{
+ return (sect->flags & OF_SYMBOL) ? (struct ol_sym *)sect : NULL;
+}
+static inline O_Symbol *seg_extsym(O_Section *sect)
+{
+ return (O_Symbol *)_seg_extsym((struct ol_sect *)sect);
+}
+
+/*
+ * Find a section or create a new section structure if it does not exist
+ * and allocate it an index value via seg_alloc().
+ */
+extern struct ol_sect *
+_ol_get_sect(const char *name, size_t ssize, size_t rsize);
+static inline O_Section *ol_get_sect(const char *name)
+{
+ return (O_Section *)_ol_get_sect(name, sizeof(O_Section), sizeof(O_Reloc));
+}
+
+/* Find a section by name without creating one */
+extern struct ol_sect *_ol_sect_by_name(const char *);
+static inline O_Section *ol_sect_by_name(const char *name)
+{
+ return (O_Section *)_ol_sect_by_name(name);
+}
+
+/* Find a section or external symbol by index; NULL if not valid */
+extern struct ol_sect *_ol_sect_by_index(int32_t index);
+static inline O_Section *ol_sect_by_index(int32_t index)
+{
+ return (O_Section *)_ol_sect_by_index(index);
+}
+
+/* Global list of sections (not including external symbols) */
+extern struct ol_sect *_ol_sect_list;
+static inline O_Section *ol_sect_list(void)
+{
+ return (O_Section *)_ol_sect_list;
+}
+
+/* Count of sections (not including external symbols) */
+extern uint64_t _ol_nsects;
+static inline uint64_t ol_nsects(void)
+{
+ return _ol_nsects;
+}
+
+/*
+ * Start a new subsection for the given section. At the moment, once a
+ * subsection has been created, it is not possible to revert to an
+ * earlier subsection. ol_sect_by_index() will return the main section
+ * structure. Returns the new section index. This is used to prevent
+ * the front end from optimizing across subsection boundaries.
+ */
+extern int32_t _ol_new_subsection(struct ol_sect *sect);
+static inline int32_t ol_new_subsection(O_Section *sect)
+{
+ return _ol_new_subsection((struct ol_sect *)sect);
+}
+
+/*
+ * Create a new symbol. If this symbol is OS_OFFS, add it to the relevant
+ * section, too. If the symbol already exists, return NULL; this is
+ * different from ol_get_section() as a single section may be invoked
+ * many times. On the contrary, the front end will prevent a single symbol
+ * from being defined more than once.
+ *
+ * If flags has OF_GLOBAL set, add it to the global symbol hash for the
+ * containing section. If flags has OF_IMPSEC set, allocate a segment
+ * index for it via seg_alloc() and add it to the section by index list.
+ */
+extern struct ol_sym *_ol_new_sym(const char *name, const struct ol_loc *v,
+ uint32_t flags, size_t size);
+static inline O_Symbol *ol_new_sym(const char *name, const struct ol_loc *v,
+ uint32_t flags)
+{
+ return (O_Symbol *)_ol_new_sym(name, v, flags, sizeof(O_Symbol));
+}
+
+/* Find a symbol by name in the global namespace */
+extern struct ol_sym *_ol_sym_by_name(const char *name);
+static inline O_Symbol *ol_sym_by_name(const char *name)
+{
+ return (O_Symbol *)_ol_sym_by_name(name);
+}
+
+/*
+ * Find a symbol by address in a specific section. If no symbol is defined
+ * at that exact address, return the immediately previously defined one.
+ * If global is set, then only return global symbols.
+ */
+extern struct ol_sym *_ol_sym_by_address(struct ol_sect *sect, int64_t addr,
+ bool global);
+static inline O_Symbol *ol_sym_by_address(O_Section *sect, int64_t addr,
+ bool global)
+{
+ return (O_Symbol *)_ol_sym_by_address((struct ol_sect *)sect, addr, global);
+}
+
+/* Global list of symbols */
+extern struct ol_sym *_ol_sym_list;
+static inline O_Symbol *ol_sym_list(void)
+{
+ return (O_Symbol *)_ol_sym_list;
+}
+
+/* Global count of symbols */
+extern uint64_t _ol_nsyms;
+static inline uint64_t ol_nsyms(void)
+{
+ return _ol_nsyms;
+}
+
+#endif /* NASM_OUTLIB_H */
diff --git a/output/outobj.c b/output/outobj.c
index 9d5e4b6a..0d4d3110 100644
--- a/output/outobj.c
+++ b/output/outobj.c
@@ -833,7 +833,7 @@ static void obj_deflabel(char *name, int32_t segment,
* `first_seg'.
*/
if (!any_segs && segment == first_seg) {
- int tempint; /* ignored */
+ int tempint = 0;
if (segment != obj_segment("__NASMDEFSEG", &tempint))
nasm_panic("strange segment conditions in OBJ driver");
}
@@ -1025,7 +1025,7 @@ static void obj_out(int32_t segto, const void *data,
* segment.
*/
if (!any_segs) {
- int tempint; /* ignored */
+ int tempint = 0;
if (segto != obj_segment("__NASMDEFSEG", &tempint))
nasm_panic("strange segment conditions in OBJ driver");
}
@@ -2498,7 +2498,7 @@ static void dbgbi_linnum(const char *lnfname, int32_t lineno, int32_t segto)
* segment.
*/
if (!any_segs) {
- int tempint; /* ignored */
+ int tempint = 0;
if (segto != obj_segment("__NASMDEFSEG", &tempint))
nasm_panic("strange segment conditions in OBJ driver");
}
diff --git a/test/Makefile b/test/Makefile
index 5f0676b0..e09e1148 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -21,16 +21,19 @@ $(NASM):
$(NASM) $(NASMOPT) -f srec -o $@ -MD $@.dep -l $@.lst $<
%.o: %.asm $(NASMDEP)
- $(NASM) $(NASMOPT) -f elf32 -o $@ -MD $@.dep -l $@.lst $<
+ $(NASM) $(NASMOPT) -f elf32 -gdwarf -o $@ -MD $@.dep -l $@.lst $<
+
+%.ox: %.asm $(NASMDEP)
+ $(NASM) $(NASMOPT) -f elfx32 -gdwarf -o $@ -MD $@.dep -l $@.lst $<
%.o64: %.asm $(NASMDEP)
- $(NASM) $(NASMOPT) -f elf64 -o $@ -MD $@.dep -l $@.lst $<
+ $(NASM) $(NASMOPT) -f elf64 -gdwarf -o $@ -MD $@.dep -l $@.lst $<
%.aout: %.asm $(NASMDEP)
$(NASM) $(NASMOPT) -f aout -o $@ -MD $@.dep -l $@.lst $<
%.obj: %.asm $(NASMDEP)
- $(NASM) $(NASMOPT) -f obj -o $@ -MD $@.dep -l $@.lst $<
+ $(NASM) $(NASMOPT) -f obj -gborland -F -o $@ -MD $@.dep -l $@.lst $<
%.rdf: %.asm $(NASMDEP)
$(NASM) $(NASMOPT) -f rdf -o $@ -MD $@.dep -l $@.lst $<
@@ -42,19 +45,19 @@ $(NASM):
$(NASM) $(NASMOPT) -f coff -o $@ -MD $@.dep -l $@.lst $<
%.win32: %.asm $(NASMDEP)
- $(NASM) $(NASMOPT) -f win32 -o $@ -MD $@.dep -l $@.lst $<
+ $(NASM) $(NASMOPT) -f win32 -gcv8 -o $@ -MD $@.dep -l $@.lst $<
%.win64: %.asm $(NASMDEP)
- $(NASM) $(NASMOPT) -f win64 -o $@ -MD $@.dep -l $@.lst $<
+ $(NASM) $(NASMOPT) -f win64 -gcv8 -o $@ -MD $@.dep -l $@.lst $<
%.mo32: %.asm $(NASMDEP)
- $(NASM) $(NASMOPT) -f macho32 -o $@ -MD $@.dep -l $@.lst $<
+ $(NASM) $(NASMOPT) -f macho32 -gdwarf -o $@ -MD $@.dep -l $@.lst $<
%.mo64: %.asm $(NASMDEP)
- $(NASM) $(NASMOPT) -f macho64 -o $@ -MD $@.dep -l $@.lst $<
+ $(NASM) $(NASMOPT) -f macho64 -gdwarf -o $@ -MD $@.dep -l $@.lst $<
%.dbg: %.asm $(NASMDEP)
- $(NASM) $(NASMOPT) -f dbg -o $@ -MD $@.dep -l $@.lst $<
+ $(NASM) $(NASMOPT) -f dbg -gdbg -o $@ -MD $@.dep -l $@.lst $<
%.asm: %.pl
$(PERL) $< > $@
diff --git a/test/a64.asm b/test/a64.asm
new file mode 100644
index 00000000..9311624e
--- /dev/null
+++ b/test/a64.asm
@@ -0,0 +1,22 @@
+ bits 64
+start:
+ invlpga eax,ecx
+ invlpga rax,ecx
+ jecxz start
+ jrcxz start
+ loop start,ecx
+ loop start,rcx
+ loope start,ecx
+ loope start,rcx
+ loopz start,ecx
+ loopz start,rcx
+ loopne start,ecx
+ loopne start,rcx
+ loopnz start,ecx
+ loopnz start,rcx
+ clzero eax
+ clzero rax
+ movdir64b eax,[edi]
+ movdir64b rax,[rdi]
+ umonitor eax
+ umonitor rax
diff --git a/test/binoverflow.asm b/test/binoverflow.asm
new file mode 100644
index 00000000..55b48e85
--- /dev/null
+++ b/test/binoverflow.asm
@@ -0,0 +1,37 @@
+;; BR 3392655: relocation overflow during bin format link
+
+ [map all binoverflow.map]
+
+ org 7C00h
+
+%macro br3392655 1
+ bits %1
+
+ section .text.%1
+start%1:
+
+mov al, var%1
+%if %1 == 64
+mov sil, var%1
+%endif
+
+mov al, foo%1
+%if %1 == 64
+mov sil, foo%1
+%endif
+
+mov al, start%1
+%if %1 == 64
+mov sil, start%1
+%endif
+
+ align 16
+var%1: db 0
+
+ align 256
+foo%1: db 0
+%endmacro
+
+ br3392655 16
+ br3392655 32
+ br3392655 64
diff --git a/test/br3392607.asm b/test/br3392607.asm
new file mode 100644
index 00000000..a61eafc3
--- /dev/null
+++ b/test/br3392607.asm
@@ -0,0 +1,2 @@
+BITS 64
+ vpshldvw xmm0{k1}{z}, xmm1, xmm2
diff --git a/test/br3392626.asm b/test/br3392626.asm
new file mode 100644
index 00000000..de4ad8ee
--- /dev/null
+++ b/test/br3392626.asm
@@ -0,0 +1,6 @@
+ ; line 1
+%rep 3 ; line 2
+ ; line 3
+ db 26h ; line 4
+%endrep ; line 5
+ ; line 6
diff --git a/test/br3392640.asm b/test/br3392640.asm
new file mode 100644
index 00000000..e593be9e
--- /dev/null
+++ b/test/br3392640.asm
@@ -0,0 +1,4 @@
+ %imacro mac 1-2
+ j%+1
+ %endmacro
+ mac c, label
diff --git a/test/br3392660.asm b/test/br3392660.asm
new file mode 100644
index 00000000..737fb616
--- /dev/null
+++ b/test/br3392660.asm
@@ -0,0 +1,9 @@
+%macro coreloop 1
+ .count_%+1:
+ .no_run_before_%+1:
+ .broken_run_before_%-1:
+%endmacro
+
+label:
+ coreloop z
+ coreloop nz
diff --git a/test/br3392661.asm b/test/br3392661.asm
new file mode 100644
index 00000000..9a349d19
--- /dev/null
+++ b/test/br3392661.asm
@@ -0,0 +1,8 @@
+section .text
+
+global _start
+
+_start:
+ mov rdi, 0 ; Exit status
+ mov rax, 60 ; Exit syscall number
+ syscall
diff --git a/test/br3392667.asm b/test/br3392667.asm
new file mode 100644
index 00000000..540cafe9
--- /dev/null
+++ b/test/br3392667.asm
Binary files differ
diff --git a/test/br3392668-3.asm b/test/br3392668-3.asm
new file mode 100644
index 00000000..c662cb7d
--- /dev/null
+++ b/test/br3392668-3.asm
Binary files differ
diff --git a/test/br3392669-57.asm b/test/br3392669-57.asm
new file mode 100644
index 00000000..71a07cb8
--- /dev/null
+++ b/test/br3392669-57.asm
Binary files differ
diff --git a/test/defalias.asm b/test/defalias.asm
new file mode 100644
index 00000000..1641a1f1
--- /dev/null
+++ b/test/defalias.asm
@@ -0,0 +1,52 @@
+%defalias foo bar
+%ifdef foo
+ %error "foo should not be defined here!"
+%endif
+
+%define foo 33
+%ifndef foo
+ %error "foo should be defined here!"
+%endif
+%ifndef bar
+ %error "bar should be defined here!"
+%endif
+%if bar != 33
+ %error "bar should have the value 33 here"
+%endif
+
+%define bar 34
+%if foo != 34
+ %error "foo should have the value 34 here"
+%endif
+
+%undef foo
+%ifdef foo
+ %error "foo should not be defined here!"
+%endif
+%ifdef bar
+ %error "bar should not be defined here!"
+%endif
+
+%ifndefalias foo
+ %error "foo was removed as an alias!"
+%endif
+
+%define bar 35
+%if foo != 35
+ %error "foo should have the value 35 here"
+%endif
+
+%define foo 36
+%if bar != 36
+ %error "bar should have the value 36 here"
+%endif
+
+%undefalias foo
+%ifdef foo
+ %error "foo is still defined after %undefalias"
+%elifdefalias foo
+ %error "foo is undefined, but still an alias"
+%endif
+%ifndef bar
+ %error "bar disappeared after %undefalias foo"
+%endif
diff --git a/test/dup.asm b/test/dup.asm
new file mode 100644
index 00000000..62785628
--- /dev/null
+++ b/test/dup.asm
@@ -0,0 +1,36 @@
+ bits 32
+
+ db 33
+ db (44)
+; db (44,55) -- error
+ db %(44,55)
+ db %('XX','YY')
+ db ('AA')
+ db %('BB')
+ db ?
+ db 6 dup (33)
+ db 6 dup (33, 34)
+ db 6 dup (33, 34), 35
+ db 7 dup (99)
+ db 7 dup dword (?, word ?,?)
+ dw byte (?,44)
+
+ dw 3 dup (0xcc, 4 dup byte ('PQR'), ?), 0xabcd
+
+ dd 16 dup (0xaaaa, ?, 0xbbbbbb)
+ dd 64 dup (?)
+
+ resb 1
+ resb 2
+ resb 4
+ resb 8
+
+ resw 1
+ resw 2
+ resw 4
+ resw 8
+
+ resq 1
+ resq 2
+ resq 4
+ resq 8
diff --git a/test/emptyarg.asm b/test/emptyarg.asm
new file mode 100644
index 00000000..af02e378
--- /dev/null
+++ b/test/emptyarg.asm
@@ -0,0 +1,147 @@
+%define EMPTY
+
+%macro bar 1
+ db "bar", __LINE__, %0, %1
+%endmacro
+
+%macro baz 2
+ db "baz", __LINE__, %0, %1, %2
+%endmacro
+
+%macro nothing 0
+ db "nothing", __LINE__, %0
+%endmacro
+
+%macro xyzzy 1-2
+ db "xyzzy", __LINE__, %0, %1, %2, %3
+%endmacro
+
+%macro vararg 0-*
+ db "vararg", __LINE__, %0
+ %assign %%i 1
+ %rep %0
+ db "vararg arg ", %%i, %1
+ %rotate 1
+ %assign %%i %%i + 1
+ %endrep
+%endmacro
+
+%macro defargs 1-5 def2, def3, def4, def5
+ db "defargs", __LINE__, %0, %1, %2, %3, %4, %5
+%endmacro
+
+%macro ivar 1
+ vararg %1
+%endmacro
+
+%macro foo 1-2
+ db "foo", __LINE__, %0, %1, %2
+ bar %2
+ bar {%2}
+ bar %2,
+ bar {%2},
+ baz %1,%2
+ baz {%1},{%2}
+ nothing %1
+ nothing %2
+ xyzzy "meep",%1,%2,
+ xyzzy "meep","meep",%1,%2
+ xyzzy "alpha","bravo",
+ xyzzy "with","empty",EMPTY
+%endmacro
+
+%macro orange 1
+ db %{1:1}
+%endmacro
+
+%macro prange1 2-3
+ db %{1:2}, 0%3
+%endmacro
+
+%macro prange2 1-3 'two', 'three'
+ db %{1:3}
+%endmacro
+
+ db 4,
+ nothing
+ nothing 1
+ nothing ; foo
+ nothing EMPTY
+
+flup: foo 1,2
+ foo 3
+ bar
+ bar EMPTY
+ foo 6,
+ foo 6, ; With space/comment
+ foo 6,EMPTY
+ baz 8,EMPTY
+ foo 6,{}
+ foo ,5
+
+ xyzzy 13,14,15,
+ xyzzy 13,14,15,EMPTY
+ xyzzy 20,21
+ xyzzy 22,23,
+ xyzzy 24,25,EMPTY
+ xyzzy 26,27,,
+ xyzzy 28,29,EMPTY,EMPTY
+
+ vararg
+ vararg EMPTY
+ vararg ,
+ vararg 10
+ vararg 11,
+ vararg 12,EMPTY
+ vararg 13,14,15,
+ vararg 13,14,15,EMPTY
+ vararg 20,21
+ vararg 22,23,
+ vararg 24,25,EMPTY
+ vararg 26,27,,
+ vararg 28,29,EMPTY,EMPTY
+
+ ivar {}
+ ivar {EMPTY}
+ ivar EMPTY
+ ivar ,
+ ivar {,}
+ ivar {60}
+ ivar {61,}
+ ivar {62,EMPTY}
+ ivar {63,64,65,}
+ ivar {63,64,65,EMPTY}
+ ivar {70,71}
+ ivar {72,73,}
+ ivar {74,75,EMPTY}
+ ivar {76,77,,}
+ ivar {78,79,EMPTY,EMPTY}
+
+ defargs EMPTY
+ defargs 91
+ defargs 91,92
+ defargs 91,92,93
+ defargs 91,92,93,94
+ defargs 91,92,93,94,95
+ defargs ,
+ defargs 91,
+ defargs 91,92,
+ defargs 91,92,93,
+ defargs 91,92,93,94,
+ defargs 91,92,93,94,95,
+
+ prange1 101
+ prange1 101, 102
+ prange1 101, 102, 103
+ prange2 121
+ prange2 121, 122
+ prange2 121, 122, 123
+ prange2 {121}
+ prange2 {121,121}
+ prange2 {121},{122}
+ prange2 {121},122,{123}
+ prange2 121,{122,122},123
+
+ orange 130
+ orange 130, 131
+ orange {130, 131}
diff --git a/test/exitrep.asm b/test/exitrep.asm
index 4e1b6e3c..755f05d5 100644
--- a/test/exitrep.asm
+++ b/test/exitrep.asm
@@ -1,16 +1,40 @@
-%macro testrep 0.nolist
+%macro testrep 0-1
%assign i 1
- %rep 4
+ %rep %1 4
mov eax,i
%if i==3
%exitrep
%endif
mov ebx,i
+ %warning in %?%1 iteration i
%if i >= 3
%error iteration i should not be seen
%endif
%assign i i+1
%endrep
+ ret
%endmacro
-testrep
+%macro testrep_nl 0-1.nolist
+ %assign i 1
+ %rep %1 4
+ mov eax,i
+ %if i==3
+ %exitrep
+ %endif
+ %warning in %?%1 iteration i
+ mov ebx,i
+ %if i >= 3
+ %error iteration i should not be seen
+ %endif
+ %assign i i+1
+ %endrep
+ ret
+%endmacro
+
+
+ testrep
+ testrep .nolist
+
+ testrep_nl
+ testrep_nl .nolist
diff --git a/test/ifdef.asm b/test/ifdef.asm
new file mode 100644
index 00000000..606cbd27
--- /dev/null
+++ b/test/ifdef.asm
@@ -0,0 +1,7 @@
+%define FOO(x) x
+%ifndef FOO
+ %define FOO(x) _ %+ x
+%endif
+
+FOO(this):
+ jmp this
diff --git a/test/include-self.asm b/test/include-self.asm
new file mode 100644
index 00000000..234e8ea4
--- /dev/null
+++ b/test/include-self.asm
@@ -0,0 +1,2 @@
+; Test an infinite %include loop
+%include "include-self.asm"
diff --git a/test/require.asm b/test/require.asm
new file mode 100644
index 00000000..169c5638
--- /dev/null
+++ b/test/require.asm
@@ -0,0 +1,2 @@
+%require 'require.asm'
+ db 1
diff --git a/test/xdefine.asm b/test/xdefine.asm
new file mode 100644
index 00000000..180c0305
--- /dev/null
+++ b/test/xdefine.asm
@@ -0,0 +1,15 @@
+%idefine d dword
+%define _1digits_nocheck(d) (((d)% 10)+'0')
+%xdefine _1digits(d) (!!(d/10)*(1<<32)+ _1digits_nocheck(d))
+
+ db _1digits(8) ; Should be 0x38
+
+%define n 0x21
+%xdefine ctr n
+%define n 0x22
+
+ db ctr, n ; Should be 0x21, 0x22
+
+%define MNSUFFIX
+%define MNCURRENT TEST%[MNSUFFIX]
+%xdefine var MNCURRENT
diff --git a/test/xpaste.asm b/test/xpaste.asm
new file mode 100644
index 00000000..cb994588
--- /dev/null
+++ b/test/xpaste.asm
@@ -0,0 +1,6 @@
+%iassign OWORD_size 16 ; octo-word
+%idefine sizeof(_x_) _x_%+_size
+
+%define ptr eax+sizeof(oword)
+
+movdqa [ptr], xmm1
diff --git a/tools/mkdep.pl b/tools/mkdep.pl
index 1966660d..27342c7f 100755
--- a/tools/mkdep.pl
+++ b/tools/mkdep.pl
@@ -1,7 +1,7 @@
#!/usr/bin/perl
## --------------------------------------------------------------------------
##
-## Copyright 1996-2017 The NASM Authors - All Rights Reserved
+## Copyright 1996-2020 The NASM Authors - All Rights Reserved
## See the file AUTHORS included with the NASM distribution for
## the specific copyright holders.
##
@@ -140,16 +140,15 @@ sub _insert_deps($$) {
my $cont = "\\";
my $include_command = undef;
my $selfrule = 0;
- my $do_external = 0;
my $maxline = 78; # Seems like a reasonable default
my %exclude = (); # Don't exclude anything
my @genhdrs = ();
my $external = undef;
my $raw_output = 0;
my @outfile = ();
- my $done = 0;
+ my $is_external = 0;
- while ( defined($line = <$in>) && !$done ) {
+ while ( defined($line = <$in>) ) {
if ( $line =~ /^([^\s\#\$\:]+\.h):/ ) {
# Note: we trust the first Makefile given best
my $fpath = $1;
@@ -179,10 +178,11 @@ sub _insert_deps($$) {
$selfrule = !!$val;
}
} elsif ( $line =~ /^(\s*\#?\s*EXTERNAL_DEPENDENCIES\s*=\s*)([01])\s*$/ ) {
+ # If this line is not present, we cannot externalize
$is_external = $externalize ? 1 : $force_inline ? 0 : $2+0;
$line = $1.$is_external."\n";
} elsif ( $line eq $barrier ) {
- $done = 1; # Stop reading input at barrier line
+ last; # Stop reading at barrier line
}
push @outfile, $line;
@@ -190,17 +190,20 @@ sub _insert_deps($$) {
close($in);
$is_external = $is_external && defined($external);
+ undef $external if ( !$is_external );
if ( !$is_external || $externalize ) {
print $out @outfile;
- } else {
- print $out $barrier; # Start generated file with barrier
}
+ print $out $barrier;
+
if ( $externalize ) {
- if ( $is_external && defined($include_command) ) {
+ # Just strip internal file dependency information
+ if (defined($include_command)) {
print $out "$include_command $external\n";
}
+ unlink($external);
return undef;
}
@@ -210,6 +213,8 @@ sub _insert_deps($$) {
my $ofile;
my @deps;
+ next unless (defined($dfile));
+
if ( $selfrule && $dfile eq $external ) {
$ofile = convert_file($dfile, $sep).':';
@deps = sort(keys(%deps));
diff --git a/tools/release b/tools/release
index a0b79461..f353425a 100755
--- a/tools/release
+++ b/tools/release
@@ -66,7 +66,7 @@ mv nasm-"$version".tar.gz nasm-"$version".tar.bz2 nasm-"$version".tar.xz ..
# Create zipfile (DOS convention: no prefix, convert file endings)
cd nasm-"$version"
-binext='jpg zip ico png pdf bin o obj exe com'
+binext='jpg zip ico png pdf bin o obj exe com a lib xz'
for e in $binext; do
xbin="$xbin -x *.$e -x *.$e.t"
ibin="$ibin -i *.$e -i *.$e.t"
@@ -93,7 +93,8 @@ cat main | xargs rm -f
# Delete empty subdirectories
find nasm-"$version"/doc -type d -exec rmdir '{}' \; 2>/dev/null || true
-# Create doc tarfile
+# Create doc tarfile (don't include nasmdoc.pdf.xz as it is redundant)
+rm -f nasm-"$version"/doc/*.pdf.xz
tar cvvf nasm-"$version"-xdoc.tar nasm-"$version"/doc
xz -9ek nasm-"$version"-xdoc.tar
bzip2 -9k nasm-"$version"-xdoc.tar
diff --git a/travis/test/_version.stdout b/travis/test/_version.stdout
index 60f885f2..07a71a55 100644
--- a/travis/test/_version.stdout
+++ b/travis/test/_version.stdout
@@ -1 +1 @@
-NASM version 2.15rc0 compiled on Nov 3 2018 \ No newline at end of file
+NASM version 2.16rc0 compiled on Jul 3 2020 \ No newline at end of file
diff --git a/travis/test/avx512f.bin.t b/travis/test/avx512f.bin.t
new file mode 100644
index 00000000..d021e674
--- /dev/null
+++ b/travis/test/avx512f.bin.t
Binary files differ
diff --git a/travis/test/avx512f.json b/travis/test/avx512f.json
index 4537b4a3..0ad5c159 100644
--- a/travis/test/avx512f.json
+++ b/travis/test/avx512f.json
@@ -6,8 +6,7 @@
"source": "avx512f.asm",
"option": "-O0 -DSRC",
"target": [
- { "stderr": "avx512f.stderr" }
+ { "output": "avx512f.bin" }
],
- "error": "expected"
}
]
diff --git a/travis/test/avx512f.stderr b/travis/test/avx512f.stderr
deleted file mode 100644
index 8e52fbcc..00000000
--- a/travis/test/avx512f.stderr
+++ /dev/null
@@ -1,572 +0,0 @@
-./travis/test/avx512f.asm:4398: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4399: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4400: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4401: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4402: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4403: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4404: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4405: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4406: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4407: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4408: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4409: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4410: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4411: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4412: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4413: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4414: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4415: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4416: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4417: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4418: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4419: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4420: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4421: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4422: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4423: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4424: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4425: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4426: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4427: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4428: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4429: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4430: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4431: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4432: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4433: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4434: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4435: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4436: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4437: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4438: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4439: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4440: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4441: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4442: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4443: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4444: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4445: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4446: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4447: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4448: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4449: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4450: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4451: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4452: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4453: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4454: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4455: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4456: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4457: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4458: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4459: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4460: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4461: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4462: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4529: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4530: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4531: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4532: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4533: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4534: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4535: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4536: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4537: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4538: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4539: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4540: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4541: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4542: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4543: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4544: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4545: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4546: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4547: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4548: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4549: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4550: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4551: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4552: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4553: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4554: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4555: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4556: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4557: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4558: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4559: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4560: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4561: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4562: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4563: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4564: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4565: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4566: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4567: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4568: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4569: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4570: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4571: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4572: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4573: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4574: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4575: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4576: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4577: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4578: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4579: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4580: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4581: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4582: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4583: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4584: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4585: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4586: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4587: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4588: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4589: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4590: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4591: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4592: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4593: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4608: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4609: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4610: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4611: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4612: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4613: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4614: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4615: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4616: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4617: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4618: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4619: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4620: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4621: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4622: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4623: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4624: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4625: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4626: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4627: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4628: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4629: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4630: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4631: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4632: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4633: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4634: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4635: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4636: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4637: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4638: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4639: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4640: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4641: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4642: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4643: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4644: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4645: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4646: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4647: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4648: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4649: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4650: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4651: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4652: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4653: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4654: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4655: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4656: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4657: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4658: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4659: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4660: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4661: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4662: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4663: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4664: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4665: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4666: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4667: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4668: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4669: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4670: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4671: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4672: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4673: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4674: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4675: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4676: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4677: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4678: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4679: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4680: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4681: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4682: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4683: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4684: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4685: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4700: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4701: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4702: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4703: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4704: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4705: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4706: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4707: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4708: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4709: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4710: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4711: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4712: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4713: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4714: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4715: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4716: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4717: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4718: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4719: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4720: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4721: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4722: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4723: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4724: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4725: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4726: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4727: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4728: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4729: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4730: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4731: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4732: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4733: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4734: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4735: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4736: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4737: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4738: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4739: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4740: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4741: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4742: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4743: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4744: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4745: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4746: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4747: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4748: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4749: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4750: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4751: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4752: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4753: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4754: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4755: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4756: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4757: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4758: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4759: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4760: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4761: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4762: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4763: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4764: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4765: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4766: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4767: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4768: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4769: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4770: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4771: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4772: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4773: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4774: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4775: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4776: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here
-./travis/test/avx512f.asm:4777: error: parser: instruction expected
-./travis/test/avx512f.asm:16: ... from macro `testcase' defined here \ No newline at end of file
diff --git a/travis/test/utf-error.stderr b/travis/test/utf-error.stderr
index c4b74a20..5d2786da 100644
--- a/travis/test/utf-error.stderr
+++ b/travis/test/utf-error.stderr
@@ -1,18 +1,15 @@
./travis/test/utf.asm:63: error: __?utf16?__ must be followed by a string constant
./travis/test/utf.asm:64: error: __?utf16?__ must be followed by a string constant
./travis/test/utf.asm:65: error: unterminated __?utf16?__ function
-./travis/test/utf.asm:65: error: comma expected after operand 2
./travis/test/utf.asm:66: error: unterminated __?utf16?__ function
./travis/test/utf.asm:67: error: invalid input string to __?utf16?__
./travis/test/utf.asm:69: error: __?utf16le?__ must be followed by a string constant
./travis/test/utf.asm:70: error: __?utf16le?__ must be followed by a string constant
./travis/test/utf.asm:71: error: unterminated __?utf16le?__ function
-./travis/test/utf.asm:71: error: comma expected after operand 2
./travis/test/utf.asm:72: error: unterminated __?utf16le?__ function
./travis/test/utf.asm:73: error: invalid input string to __?utf16le?__
./travis/test/utf.asm:75: error: __?utf16be?__ must be followed by a string constant
./travis/test/utf.asm:76: error: __?utf16be?__ must be followed by a string constant
./travis/test/utf.asm:77: error: unterminated __?utf16be?__ function
-./travis/test/utf.asm:77: error: comma expected after operand 2
./travis/test/utf.asm:78: error: unterminated __?utf16be?__ function
./travis/test/utf.asm:79: error: invalid input string to __?utf16be?__
diff --git a/travis/test/weirdpaste.i.t b/travis/test/weirdpaste.i.t
index ac7ddf08..bf2acd6c 100644
--- a/travis/test/weirdpaste.i.t
+++ b/travis/test/weirdpaste.i.t
@@ -1,27 +1,20 @@
-%line 3+1 ./travis/test/weirdpaste.asm
-
-
-
-%line 10+1 ./travis/test/weirdpaste.asm
-
+%line 8+1 ./travis/test/weirdpaste.asm
dw 25
+%line 12+1 ./travis/test/weirdpaste.asm
%line 18+1 ./travis/test/weirdpaste.asm
+%line 15+1 ./travis/test/weirdpaste.asm
dd 2067830734
-%line 19+0 ./travis/test/weirdpaste.asm
dd 1e+36
-%line 20+1 ./travis/test/weirdpaste.asm
+%line 15+1 ./travis/test/weirdpaste.asm
dd 1664279731
-%line 20+0 ./travis/test/weirdpaste.asm
dd 33e+20
-%line 21+1 ./travis/test/weirdpaste.asm
+%line 15+1 ./travis/test/weirdpaste.asm
dd 0
-%line 21+0 ./travis/test/weirdpaste.asm
dd 0e+2
-%line 22+1 ./travis/test/weirdpaste.asm
+%line 15+1 ./travis/test/weirdpaste.asm
dd 1206542336
-%line 22+0 ./travis/test/weirdpaste.asm
dd 1.2e+5
%line 23+1 ./travis/test/weirdpaste.asm
diff --git a/version b/version
index 91d11b10..015a89ee 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-2.15rc0
+2.16rc0
diff --git a/x86/iflags.ph b/x86/iflags.ph
index 8f0a80fd..2c05b293 100644
--- a/x86/iflags.ph
+++ b/x86/iflags.ph
@@ -83,6 +83,7 @@ if_("AVX512VPOPCNTDQ", "AVX-512 VPOPCNTD/VPOPCNTQ");
if_("AVX5124FMAPS", "AVX-512 4-iteration multiply-add");
if_("AVX5124VNNIW", "AVX-512 4-iteration dot product");
if_("SGX", "Intel Software Guard Extensions (SGX)");
+if_("CET", "Intel Control-Flow Enforcement Technology (CET)");
# Put these last [hpa: why?]
if_("OBSOLETE", "Instruction removed from architecture");
diff --git a/x86/insns.dat b/x86/insns.dat
index 0f18e826..980c5943 100644
--- a/x86/insns.dat
+++ b/x86/insns.dat
@@ -1,6 +1,6 @@
;; --------------------------------------------------------------------------
;;
-;; Copyright 1996-2019 The NASM Authors - All Rights Reserved
+;; Copyright 1996-2020 The NASM Authors - All Rights Reserved
;; See the file AUTHORS included with the NASM distribution for
;; the specific copyright holders.
;;
@@ -344,8 +344,8 @@ CMPXCHG486 mem,reg16 [mr: o16 0f a7 /r] 486,SM,UNDOC,ND,LOCK,OBSOLETE
CMPXCHG486 reg16,reg16 [mr: o16 0f a7 /r] 486,UNDOC,ND,OBSOLETE
CMPXCHG486 mem,reg32 [mr: o32 0f a7 /r] 486,SM,UNDOC,ND,LOCK,OBSOLETE
CMPXCHG486 reg32,reg32 [mr: o32 0f a7 /r] 486,UNDOC,ND,OBSOLETE
-CMPXCHG8B mem [m: hle norexw 0f c7 /1] PENT,LOCK
-CMPXCHG16B mem [m: o64 0f c7 /1] X64,LOCK
+CMPXCHG8B mem64 [m: hle norexw 0f c7 /1] PENT,LOCK
+CMPXCHG16B mem128 [m: o64 0f c7 /1] X64,LOCK
CPUID void [ 0f a2] PENT
CPU_READ void [ 0f 3d] PENT,CYRIX
CPU_WRITE void [ 0f 3c] PENT,CYRIX
@@ -678,7 +678,7 @@ IRETQ void [ o64 cf] X64
IRETW void [ o16 cf] 8086
JCXZ imm [i: a16 e3 rel8] 8086,NOLONG
JECXZ imm [i: a32 e3 rel8] 386
-JRCXZ imm [i: a64 e3 rel8] X64
+JRCXZ imm [i: o64nw a64 e3 rel8] X64
JMP imm|short [i: eb rel8] 8086
JMP imm [i: jmp8 eb rel8] 8086,ND
JMP imm [i: odf e9 rel] 8086,BND
@@ -1402,14 +1402,14 @@ UD0 void [ 0f ff] 186,OBSOLETE
UD0 reg16,rm16 [rm: o16 0f ff /r] 186
UD0 reg32,rm32 [rm: o32 0f ff /r] 186
UD0 reg64,rm64 [rm: o64 0f ff /r] 186
-UD1 reg,rm16 [rm: o16 0f b9 /r] 186
-UD1 reg,rm32 [rm: o32 0f b9 /r] 186
-UD1 reg,rm64 [rm: o64 0f b9 /r] 186
+UD1 reg16,rm16 [rm: o16 0f b9 /r] 186
+UD1 reg32,rm32 [rm: o32 0f b9 /r] 186
+UD1 reg64,rm64 [rm: o64 0f b9 /r] 186
UD1 void [ 0f b9] 186,ND
UD2B void [ 0f b9] 186,ND
-UD2B reg,rm16 [rm: o16 0f b9 /r] 186,ND
-UD2B reg,rm32 [rm: o32 0f b9 /r] 186,ND
-UD2B reg,rm64 [rm: o64 0f b9 /r] 186,ND
+UD2B reg16,rm16 [rm: o16 0f b9 /r] 186,ND
+UD2B reg32,rm32 [rm: o32 0f b9 /r] 186,ND
+UD2B reg64,rm64 [rm: o64 0f b9 /r] 186,ND
UD2 void [ 0f 0b] 186
UD2A void [ 0f 0b] 186,ND
UMOV mem,reg8 [mr: np 0f 10 /r] 386,UNDOC,SM,ND
@@ -3796,6 +3796,374 @@ VBROADCASTSS zmmreg|mask|z,mem32 [rm:t1s: evex.512.66.0f38.w0
VBROADCASTSS xmmreg|mask|z,xmmreg [rm: evex.128.66.0f38.w0 18 /r ] AVX512VL,AVX512,FUTURE
VBROADCASTSS ymmreg|mask|z,xmmreg [rm: evex.256.66.0f38.w0 18 /r ] AVX512VL,AVX512,FUTURE
VBROADCASTSS zmmreg|mask|z,xmmreg [rm: evex.512.66.0f38.w0 18 /r ] AVX512,FUTURE
+VCMPEQPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 00 ] AVX512VL,AVX512,FUTURE
+VCMPEQPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 00 ] AVX512VL,AVX512,FUTURE
+VCMPEQPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 00 ] AVX512,FUTURE
+VCMPEQPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 00 ] AVX512VL,AVX512,FUTURE
+VCMPEQPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 00 ] AVX512VL,AVX512,FUTURE
+VCMPEQPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 00 ] AVX512,FUTURE
+VCMPEQSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 00 ] AVX512,FUTURE
+VCMPEQSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 00 ] AVX512,FUTURE
+VCMPEQ_OQPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 00 ] AVX512VL,AVX512,FUTURE
+VCMPEQ_OQPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 00 ] AVX512VL,AVX512,FUTURE
+VCMPEQ_OQPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 00 ] AVX512,FUTURE
+VCMPEQ_OQPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 00 ] AVX512VL,AVX512,FUTURE
+VCMPEQ_OQPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 00 ] AVX512VL,AVX512,FUTURE
+VCMPEQ_OQPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 00 ] AVX512,FUTURE
+VCMPEQ_OQSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 00 ] AVX512,FUTURE
+VCMPEQ_OQSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 00 ] AVX512,FUTURE
+VCMPLTPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 01 ] AVX512VL,AVX512,FUTURE
+VCMPLTPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 01 ] AVX512VL,AVX512,FUTURE
+VCMPLTPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 01 ] AVX512,FUTURE
+VCMPLTPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 01 ] AVX512VL,AVX512,FUTURE
+VCMPLTPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 01 ] AVX512VL,AVX512,FUTURE
+VCMPLTPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 01 ] AVX512,FUTURE
+VCMPLTSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 01 ] AVX512,FUTURE
+VCMPLTSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 01 ] AVX512,FUTURE
+VCMPLT_OSPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 01 ] AVX512VL,AVX512,FUTURE
+VCMPLT_OSPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 01 ] AVX512VL,AVX512,FUTURE
+VCMPLT_OSPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 01 ] AVX512,FUTURE
+VCMPLT_OSPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 01 ] AVX512VL,AVX512,FUTURE
+VCMPLT_OSPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 01 ] AVX512VL,AVX512,FUTURE
+VCMPLT_OSPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 01 ] AVX512,FUTURE
+VCMPLT_OSSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 01 ] AVX512,FUTURE
+VCMPLT_OSSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 01 ] AVX512,FUTURE
+VCMPLEPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 02 ] AVX512VL,AVX512,FUTURE
+VCMPLEPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 02 ] AVX512VL,AVX512,FUTURE
+VCMPLEPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 02 ] AVX512,FUTURE
+VCMPLEPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 02 ] AVX512VL,AVX512,FUTURE
+VCMPLEPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 02 ] AVX512VL,AVX512,FUTURE
+VCMPLEPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 02 ] AVX512,FUTURE
+VCMPLESD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 02 ] AVX512,FUTURE
+VCMPLESS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 02 ] AVX512,FUTURE
+VCMPLE_OSPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 02 ] AVX512VL,AVX512,FUTURE
+VCMPLE_OSPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 02 ] AVX512VL,AVX512,FUTURE
+VCMPLE_OSPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 02 ] AVX512,FUTURE
+VCMPLE_OSPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 02 ] AVX512VL,AVX512,FUTURE
+VCMPLE_OSPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 02 ] AVX512VL,AVX512,FUTURE
+VCMPLE_OSPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 02 ] AVX512,FUTURE
+VCMPLE_OSSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 02 ] AVX512,FUTURE
+VCMPLE_OSSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 02 ] AVX512,FUTURE
+VCMPUNORDPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 03 ] AVX512VL,AVX512,FUTURE
+VCMPUNORDPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 03 ] AVX512VL,AVX512,FUTURE
+VCMPUNORDPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 03 ] AVX512,FUTURE
+VCMPUNORDPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 03 ] AVX512VL,AVX512,FUTURE
+VCMPUNORDPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 03 ] AVX512VL,AVX512,FUTURE
+VCMPUNORDPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 03 ] AVX512,FUTURE
+VCMPUNORDSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 03 ] AVX512,FUTURE
+VCMPUNORDSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 03 ] AVX512,FUTURE
+VCMPUNORD_QPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 03 ] AVX512VL,AVX512,FUTURE
+VCMPUNORD_QPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 03 ] AVX512VL,AVX512,FUTURE
+VCMPUNORD_QPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 03 ] AVX512,FUTURE
+VCMPUNORD_QPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 03 ] AVX512VL,AVX512,FUTURE
+VCMPUNORD_QPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 03 ] AVX512VL,AVX512,FUTURE
+VCMPUNORD_QPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 03 ] AVX512,FUTURE
+VCMPUNORD_QSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 03 ] AVX512,FUTURE
+VCMPUNORD_QSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 03 ] AVX512,FUTURE
+VCMPNEQPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 04 ] AVX512VL,AVX512,FUTURE
+VCMPNEQPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 04 ] AVX512VL,AVX512,FUTURE
+VCMPNEQPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 04 ] AVX512,FUTURE
+VCMPNEQPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 04 ] AVX512VL,AVX512,FUTURE
+VCMPNEQPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 04 ] AVX512VL,AVX512,FUTURE
+VCMPNEQPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 04 ] AVX512,FUTURE
+VCMPNEQSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 04 ] AVX512,FUTURE
+VCMPNEQSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 04 ] AVX512,FUTURE
+VCMPNEQ_UQPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 04 ] AVX512VL,AVX512,FUTURE
+VCMPNEQ_UQPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 04 ] AVX512VL,AVX512,FUTURE
+VCMPNEQ_UQPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 04 ] AVX512,FUTURE
+VCMPNEQ_UQPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 04 ] AVX512VL,AVX512,FUTURE
+VCMPNEQ_UQPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 04 ] AVX512VL,AVX512,FUTURE
+VCMPNEQ_UQPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 04 ] AVX512,FUTURE
+VCMPNEQ_UQSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 04 ] AVX512,FUTURE
+VCMPNEQ_UQSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 04 ] AVX512,FUTURE
+VCMPNLTPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 05 ] AVX512VL,AVX512,FUTURE
+VCMPNLTPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 05 ] AVX512VL,AVX512,FUTURE
+VCMPNLTPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 05 ] AVX512,FUTURE
+VCMPNLTPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 05 ] AVX512VL,AVX512,FUTURE
+VCMPNLTPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 05 ] AVX512VL,AVX512,FUTURE
+VCMPNLTPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 05 ] AVX512,FUTURE
+VCMPNLTSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 05 ] AVX512,FUTURE
+VCMPNLTSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 05 ] AVX512,FUTURE
+VCMPNLT_USPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 05 ] AVX512VL,AVX512,FUTURE
+VCMPNLT_USPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 05 ] AVX512VL,AVX512,FUTURE
+VCMPNLT_USPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 05 ] AVX512,FUTURE
+VCMPNLT_USPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 05 ] AVX512VL,AVX512,FUTURE
+VCMPNLT_USPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 05 ] AVX512VL,AVX512,FUTURE
+VCMPNLT_USPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 05 ] AVX512,FUTURE
+VCMPNLT_USSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 05 ] AVX512,FUTURE
+VCMPNLT_USSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 05 ] AVX512,FUTURE
+VCMPNLEPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 06 ] AVX512VL,AVX512,FUTURE
+VCMPNLEPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 06 ] AVX512VL,AVX512,FUTURE
+VCMPNLEPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 06 ] AVX512,FUTURE
+VCMPNLEPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 06 ] AVX512VL,AVX512,FUTURE
+VCMPNLEPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 06 ] AVX512VL,AVX512,FUTURE
+VCMPNLEPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 06 ] AVX512,FUTURE
+VCMPNLESD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 06 ] AVX512,FUTURE
+VCMPNLESS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 06 ] AVX512,FUTURE
+VCMPNLE_USPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 06 ] AVX512VL,AVX512,FUTURE
+VCMPNLE_USPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 06 ] AVX512VL,AVX512,FUTURE
+VCMPNLE_USPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 06 ] AVX512,FUTURE
+VCMPNLE_USPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 06 ] AVX512VL,AVX512,FUTURE
+VCMPNLE_USPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 06 ] AVX512VL,AVX512,FUTURE
+VCMPNLE_USPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 06 ] AVX512,FUTURE
+VCMPNLE_USSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 06 ] AVX512,FUTURE
+VCMPNLE_USSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 06 ] AVX512,FUTURE
+VCMPORDPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 07 ] AVX512VL,AVX512,FUTURE
+VCMPORDPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 07 ] AVX512VL,AVX512,FUTURE
+VCMPORDPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 07 ] AVX512,FUTURE
+VCMPORDPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 07 ] AVX512VL,AVX512,FUTURE
+VCMPORDPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 07 ] AVX512VL,AVX512,FUTURE
+VCMPORDPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 07 ] AVX512,FUTURE
+VCMPORDSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 07 ] AVX512,FUTURE
+VCMPORDSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 07 ] AVX512,FUTURE
+VCMPORD_QPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 07 ] AVX512VL,AVX512,FUTURE
+VCMPORD_QPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 07 ] AVX512VL,AVX512,FUTURE
+VCMPORD_QPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 07 ] AVX512,FUTURE
+VCMPORD_QPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 07 ] AVX512VL,AVX512,FUTURE
+VCMPORD_QPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 07 ] AVX512VL,AVX512,FUTURE
+VCMPORD_QPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 07 ] AVX512,FUTURE
+VCMPORD_QSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 07 ] AVX512,FUTURE
+VCMPORD_QSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 07 ] AVX512,FUTURE
+VCMPEQ_UQPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 08 ] AVX512VL,AVX512,FUTURE
+VCMPEQ_UQPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 08 ] AVX512VL,AVX512,FUTURE
+VCMPEQ_UQPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 08 ] AVX512,FUTURE
+VCMPEQ_UQPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 08 ] AVX512VL,AVX512,FUTURE
+VCMPEQ_UQPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 08 ] AVX512VL,AVX512,FUTURE
+VCMPEQ_UQPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 08 ] AVX512,FUTURE
+VCMPEQ_UQSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 08 ] AVX512,FUTURE
+VCMPEQ_UQSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 08 ] AVX512,FUTURE
+VCMPNGEPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 09 ] AVX512VL,AVX512,FUTURE
+VCMPNGEPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 09 ] AVX512VL,AVX512,FUTURE
+VCMPNGEPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 09 ] AVX512,FUTURE
+VCMPNGEPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 09 ] AVX512VL,AVX512,FUTURE
+VCMPNGEPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 09 ] AVX512VL,AVX512,FUTURE
+VCMPNGEPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 09 ] AVX512,FUTURE
+VCMPNGESD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 09 ] AVX512,FUTURE
+VCMPNGESS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 09 ] AVX512,FUTURE
+VCMPNGE_USPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 09 ] AVX512VL,AVX512,FUTURE
+VCMPNGE_USPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 09 ] AVX512VL,AVX512,FUTURE
+VCMPNGE_USPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 09 ] AVX512,FUTURE
+VCMPNGE_USPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 09 ] AVX512VL,AVX512,FUTURE
+VCMPNGE_USPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 09 ] AVX512VL,AVX512,FUTURE
+VCMPNGE_USPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 09 ] AVX512,FUTURE
+VCMPNGE_USSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 09 ] AVX512,FUTURE
+VCMPNGE_USSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 09 ] AVX512,FUTURE
+VCMPNGTPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 0a ] AVX512VL,AVX512,FUTURE
+VCMPNGTPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 0a ] AVX512VL,AVX512,FUTURE
+VCMPNGTPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 0a ] AVX512,FUTURE
+VCMPNGTPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 0a ] AVX512VL,AVX512,FUTURE
+VCMPNGTPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 0a ] AVX512VL,AVX512,FUTURE
+VCMPNGTPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 0a ] AVX512,FUTURE
+VCMPNGTSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 0a ] AVX512,FUTURE
+VCMPNGTSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 0a ] AVX512,FUTURE
+VCMPNGT_USPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 0a ] AVX512VL,AVX512,FUTURE
+VCMPNGT_USPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 0a ] AVX512VL,AVX512,FUTURE
+VCMPNGT_USPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 0a ] AVX512,FUTURE
+VCMPNGT_USPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 0a ] AVX512VL,AVX512,FUTURE
+VCMPNGT_USPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 0a ] AVX512VL,AVX512,FUTURE
+VCMPNGT_USPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 0a ] AVX512,FUTURE
+VCMPNGT_USSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 0a ] AVX512,FUTURE
+VCMPNGT_USSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 0a ] AVX512,FUTURE
+VCMPFALSEPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 0b ] AVX512VL,AVX512,FUTURE
+VCMPFALSEPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 0b ] AVX512VL,AVX512,FUTURE
+VCMPFALSEPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 0b ] AVX512,FUTURE
+VCMPFALSEPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 0b ] AVX512VL,AVX512,FUTURE
+VCMPFALSEPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 0b ] AVX512VL,AVX512,FUTURE
+VCMPFALSEPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 0b ] AVX512,FUTURE
+VCMPFALSESD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 0b ] AVX512,FUTURE
+VCMPFALSESS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 0b ] AVX512,FUTURE
+VCMPFALSE_OQPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 0b ] AVX512VL,AVX512,FUTURE
+VCMPFALSE_OQPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 0b ] AVX512VL,AVX512,FUTURE
+VCMPFALSE_OQPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 0b ] AVX512,FUTURE
+VCMPFALSE_OQPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 0b ] AVX512VL,AVX512,FUTURE
+VCMPFALSE_OQPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 0b ] AVX512VL,AVX512,FUTURE
+VCMPFALSE_OQPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 0b ] AVX512,FUTURE
+VCMPFALSE_OQSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 0b ] AVX512,FUTURE
+VCMPFALSE_OQSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 0b ] AVX512,FUTURE
+VCMPNEQ_OQPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 0c ] AVX512VL,AVX512,FUTURE
+VCMPNEQ_OQPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 0c ] AVX512VL,AVX512,FUTURE
+VCMPNEQ_OQPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 0c ] AVX512,FUTURE
+VCMPNEQ_OQPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 0c ] AVX512VL,AVX512,FUTURE
+VCMPNEQ_OQPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 0c ] AVX512VL,AVX512,FUTURE
+VCMPNEQ_OQPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 0c ] AVX512,FUTURE
+VCMPNEQ_OQSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 0c ] AVX512,FUTURE
+VCMPNEQ_OQSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 0c ] AVX512,FUTURE
+VCMPGEPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 0d ] AVX512VL,AVX512,FUTURE
+VCMPGEPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 0d ] AVX512VL,AVX512,FUTURE
+VCMPGEPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 0d ] AVX512,FUTURE
+VCMPGEPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 0d ] AVX512VL,AVX512,FUTURE
+VCMPGEPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 0d ] AVX512VL,AVX512,FUTURE
+VCMPGEPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 0d ] AVX512,FUTURE
+VCMPGESD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 0d ] AVX512,FUTURE
+VCMPGESS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 0d ] AVX512,FUTURE
+VCMPGE_OSPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 0d ] AVX512VL,AVX512,FUTURE
+VCMPGE_OSPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 0d ] AVX512VL,AVX512,FUTURE
+VCMPGE_OSPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 0d ] AVX512,FUTURE
+VCMPGE_OSPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 0d ] AVX512VL,AVX512,FUTURE
+VCMPGE_OSPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 0d ] AVX512VL,AVX512,FUTURE
+VCMPGE_OSPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 0d ] AVX512,FUTURE
+VCMPGE_OSSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 0d ] AVX512,FUTURE
+VCMPGE_OSSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 0d ] AVX512,FUTURE
+VCMPGTPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 0e ] AVX512VL,AVX512,FUTURE
+VCMPGTPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 0e ] AVX512VL,AVX512,FUTURE
+VCMPGTPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 0e ] AVX512,FUTURE
+VCMPGTPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 0e ] AVX512VL,AVX512,FUTURE
+VCMPGTPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 0e ] AVX512VL,AVX512,FUTURE
+VCMPGTPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 0e ] AVX512,FUTURE
+VCMPGTSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 0e ] AVX512,FUTURE
+VCMPGTSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 0e ] AVX512,FUTURE
+VCMPGT_OSPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 0e ] AVX512VL,AVX512,FUTURE
+VCMPGT_OSPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 0e ] AVX512VL,AVX512,FUTURE
+VCMPGT_OSPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 0e ] AVX512,FUTURE
+VCMPGT_OSPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 0e ] AVX512VL,AVX512,FUTURE
+VCMPGT_OSPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 0e ] AVX512VL,AVX512,FUTURE
+VCMPGT_OSPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 0e ] AVX512,FUTURE
+VCMPGT_OSSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 0e ] AVX512,FUTURE
+VCMPGT_OSSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 0e ] AVX512,FUTURE
+VCMPTRUEPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 0f ] AVX512VL,AVX512,FUTURE
+VCMPTRUEPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 0f ] AVX512VL,AVX512,FUTURE
+VCMPTRUEPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 0f ] AVX512,FUTURE
+VCMPTRUEPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 0f ] AVX512VL,AVX512,FUTURE
+VCMPTRUEPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 0f ] AVX512VL,AVX512,FUTURE
+VCMPTRUEPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 0f ] AVX512,FUTURE
+VCMPTRUESD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 0f ] AVX512,FUTURE
+VCMPTRUESS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 0f ] AVX512,FUTURE
+VCMPTRUE_UQPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 0f ] AVX512VL,AVX512,FUTURE
+VCMPTRUE_UQPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 0f ] AVX512VL,AVX512,FUTURE
+VCMPTRUE_UQPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 0f ] AVX512,FUTURE
+VCMPTRUE_UQPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 0f ] AVX512VL,AVX512,FUTURE
+VCMPTRUE_UQPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 0f ] AVX512VL,AVX512,FUTURE
+VCMPTRUE_UQPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 0f ] AVX512,FUTURE
+VCMPTRUE_UQSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 0f ] AVX512,FUTURE
+VCMPTRUE_UQSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 0f ] AVX512,FUTURE
+VCMPEQ_OSPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 10 ] AVX512VL,AVX512,FUTURE
+VCMPEQ_OSPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 10 ] AVX512VL,AVX512,FUTURE
+VCMPEQ_OSPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 10 ] AVX512,FUTURE
+VCMPEQ_OSPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 10 ] AVX512VL,AVX512,FUTURE
+VCMPEQ_OSPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 10 ] AVX512VL,AVX512,FUTURE
+VCMPEQ_OSPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 10 ] AVX512,FUTURE
+VCMPEQ_OSSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 10 ] AVX512,FUTURE
+VCMPEQ_OSSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 10 ] AVX512,FUTURE
+VCMPLT_OQPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 11 ] AVX512VL,AVX512,FUTURE
+VCMPLT_OQPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 11 ] AVX512VL,AVX512,FUTURE
+VCMPLT_OQPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 11 ] AVX512,FUTURE
+VCMPLT_OQPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 11 ] AVX512VL,AVX512,FUTURE
+VCMPLT_OQPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 11 ] AVX512VL,AVX512,FUTURE
+VCMPLT_OQPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 11 ] AVX512,FUTURE
+VCMPLT_OQSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 11 ] AVX512,FUTURE
+VCMPLT_OQSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 11 ] AVX512,FUTURE
+VCMPLE_OQPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 12 ] AVX512VL,AVX512,FUTURE
+VCMPLE_OQPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 12 ] AVX512VL,AVX512,FUTURE
+VCMPLE_OQPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 12 ] AVX512,FUTURE
+VCMPLE_OQPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 12 ] AVX512VL,AVX512,FUTURE
+VCMPLE_OQPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 12 ] AVX512VL,AVX512,FUTURE
+VCMPLE_OQPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 12 ] AVX512,FUTURE
+VCMPLE_OQSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 12 ] AVX512,FUTURE
+VCMPLE_OQSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 12 ] AVX512,FUTURE
+VCMPUNORD_SPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 13 ] AVX512VL,AVX512,FUTURE
+VCMPUNORD_SPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 13 ] AVX512VL,AVX512,FUTURE
+VCMPUNORD_SPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 13 ] AVX512,FUTURE
+VCMPUNORD_SPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 13 ] AVX512VL,AVX512,FUTURE
+VCMPUNORD_SPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 13 ] AVX512VL,AVX512,FUTURE
+VCMPUNORD_SPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 13 ] AVX512,FUTURE
+VCMPUNORD_SSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 13 ] AVX512,FUTURE
+VCMPUNORD_SSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 13 ] AVX512,FUTURE
+VCMPNEQ_USPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 14 ] AVX512VL,AVX512,FUTURE
+VCMPNEQ_USPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 14 ] AVX512VL,AVX512,FUTURE
+VCMPNEQ_USPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 14 ] AVX512,FUTURE
+VCMPNEQ_USPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 14 ] AVX512VL,AVX512,FUTURE
+VCMPNEQ_USPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 14 ] AVX512VL,AVX512,FUTURE
+VCMPNEQ_USPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 14 ] AVX512,FUTURE
+VCMPNEQ_USSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 14 ] AVX512,FUTURE
+VCMPNEQ_USSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 14 ] AVX512,FUTURE
+VCMPNLT_UQPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 15 ] AVX512VL,AVX512,FUTURE
+VCMPNLT_UQPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 15 ] AVX512VL,AVX512,FUTURE
+VCMPNLT_UQPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 15 ] AVX512,FUTURE
+VCMPNLT_UQPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 15 ] AVX512VL,AVX512,FUTURE
+VCMPNLT_UQPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 15 ] AVX512VL,AVX512,FUTURE
+VCMPNLT_UQPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 15 ] AVX512,FUTURE
+VCMPNLT_UQSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 15 ] AVX512,FUTURE
+VCMPNLT_UQSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 15 ] AVX512,FUTURE
+VCMPNLE_UQPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 16 ] AVX512VL,AVX512,FUTURE
+VCMPNLE_UQPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 16 ] AVX512VL,AVX512,FUTURE
+VCMPNLE_UQPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 16 ] AVX512,FUTURE
+VCMPNLE_UQPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 16 ] AVX512VL,AVX512,FUTURE
+VCMPNLE_UQPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 16 ] AVX512VL,AVX512,FUTURE
+VCMPNLE_UQPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 16 ] AVX512,FUTURE
+VCMPNLE_UQSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 16 ] AVX512,FUTURE
+VCMPNLE_UQSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 16 ] AVX512,FUTURE
+VCMPORD_SPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 17 ] AVX512VL,AVX512,FUTURE
+VCMPORD_SPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 17 ] AVX512VL,AVX512,FUTURE
+VCMPORD_SPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 17 ] AVX512,FUTURE
+VCMPORD_SPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 17 ] AVX512VL,AVX512,FUTURE
+VCMPORD_SPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 17 ] AVX512VL,AVX512,FUTURE
+VCMPORD_SPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 17 ] AVX512,FUTURE
+VCMPORD_SSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 17 ] AVX512,FUTURE
+VCMPORD_SSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 17 ] AVX512,FUTURE
+VCMPEQ_USPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 18 ] AVX512VL,AVX512,FUTURE
+VCMPEQ_USPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 18 ] AVX512VL,AVX512,FUTURE
+VCMPEQ_USPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 18 ] AVX512,FUTURE
+VCMPEQ_USPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 18 ] AVX512VL,AVX512,FUTURE
+VCMPEQ_USPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 18 ] AVX512VL,AVX512,FUTURE
+VCMPEQ_USPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 18 ] AVX512,FUTURE
+VCMPEQ_USSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 18 ] AVX512,FUTURE
+VCMPEQ_USSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 18 ] AVX512,FUTURE
+VCMPNGE_UQPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 19 ] AVX512VL,AVX512,FUTURE
+VCMPNGE_UQPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 19 ] AVX512VL,AVX512,FUTURE
+VCMPNGE_UQPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 19 ] AVX512,FUTURE
+VCMPNGE_UQPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 19 ] AVX512VL,AVX512,FUTURE
+VCMPNGE_UQPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 19 ] AVX512VL,AVX512,FUTURE
+VCMPNGE_UQPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 19 ] AVX512,FUTURE
+VCMPNGE_UQSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 19 ] AVX512,FUTURE
+VCMPNGE_UQSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 19 ] AVX512,FUTURE
+VCMPNGT_UQPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 1a ] AVX512VL,AVX512,FUTURE
+VCMPNGT_UQPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 1a ] AVX512VL,AVX512,FUTURE
+VCMPNGT_UQPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 1a ] AVX512,FUTURE
+VCMPNGT_UQPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 1a ] AVX512VL,AVX512,FUTURE
+VCMPNGT_UQPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 1a ] AVX512VL,AVX512,FUTURE
+VCMPNGT_UQPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 1a ] AVX512,FUTURE
+VCMPNGT_UQSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 1a ] AVX512,FUTURE
+VCMPNGT_UQSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 1a ] AVX512,FUTURE
+VCMPFALSE_OSPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 1b ] AVX512VL,AVX512,FUTURE
+VCMPFALSE_OSPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 1b ] AVX512VL,AVX512,FUTURE
+VCMPFALSE_OSPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 1b ] AVX512,FUTURE
+VCMPFALSE_OSPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 1b ] AVX512VL,AVX512,FUTURE
+VCMPFALSE_OSPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 1b ] AVX512VL,AVX512,FUTURE
+VCMPFALSE_OSPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 1b ] AVX512,FUTURE
+VCMPFALSE_OSSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 1b ] AVX512,FUTURE
+VCMPFALSE_OSSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 1b ] AVX512,FUTURE
+VCMPNEQ_OSPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 1c ] AVX512VL,AVX512,FUTURE
+VCMPNEQ_OSPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 1c ] AVX512VL,AVX512,FUTURE
+VCMPNEQ_OSPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 1c ] AVX512,FUTURE
+VCMPNEQ_OSPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 1c ] AVX512VL,AVX512,FUTURE
+VCMPNEQ_OSPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 1c ] AVX512VL,AVX512,FUTURE
+VCMPNEQ_OSPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 1c ] AVX512,FUTURE
+VCMPNEQ_OSSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 1c ] AVX512,FUTURE
+VCMPNEQ_OSSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 1c ] AVX512,FUTURE
+VCMPGE_OQPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 1d ] AVX512VL,AVX512,FUTURE
+VCMPGE_OQPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 1d ] AVX512VL,AVX512,FUTURE
+VCMPGE_OQPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 1d ] AVX512,FUTURE
+VCMPGE_OQPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 1d ] AVX512VL,AVX512,FUTURE
+VCMPGE_OQPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 1d ] AVX512VL,AVX512,FUTURE
+VCMPGE_OQPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 1d ] AVX512,FUTURE
+VCMPGE_OQSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 1d ] AVX512,FUTURE
+VCMPGE_OQSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 1d ] AVX512,FUTURE
+VCMPGT_OQPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 1e ] AVX512VL,AVX512,FUTURE
+VCMPGT_OQPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 1e ] AVX512VL,AVX512,FUTURE
+VCMPGT_OQPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 1e ] AVX512,FUTURE
+VCMPGT_OQPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 1e ] AVX512VL,AVX512,FUTURE
+VCMPGT_OQPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 1e ] AVX512VL,AVX512,FUTURE
+VCMPGT_OQPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 1e ] AVX512,FUTURE
+VCMPGT_OQSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 1e ] AVX512,FUTURE
+VCMPGT_OQSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 1e ] AVX512,FUTURE
+VCMPTRUE_USPD kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r 1f ] AVX512VL,AVX512,FUTURE
+VCMPTRUE_USPD kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r 1f ] AVX512VL,AVX512,FUTURE
+VCMPTRUE_USPD kreg|mask,zmmreg,zmmrm512|b64|sae [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r 1f ] AVX512,FUTURE
+VCMPTRUE_USPS kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.0f.w0 c2 /r 1f ] AVX512VL,AVX512,FUTURE
+VCMPTRUE_USPS kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.0f.w0 c2 /r 1f ] AVX512VL,AVX512,FUTURE
+VCMPTRUE_USPS kreg|mask,zmmreg,zmmrm512|b32|sae [rvmi:fv: evex.nds.512.0f.w0 c2 /r 1f ] AVX512,FUTURE
+VCMPTRUE_USSD kreg|mask,xmmreg,xmmrm64|sae [rvmi:t1s: evex.nds.128.f2.0f.w1 c2 /r 1f ] AVX512,FUTURE
+VCMPTRUE_USSS kreg|mask,xmmreg,xmmrm32|sae [rvmi:t1s: evex.nds.128.f3.0f.w0 c2 /r 1f ] AVX512,FUTURE
VCMPPD kreg|mask,xmmreg,xmmrm128|b64,imm8 [rvmi:fv: evex.nds.128.66.0f.w1 c2 /r ib ] AVX512VL,AVX512,FUTURE
VCMPPD kreg|mask,ymmreg,ymmrm256|b64,imm8 [rvmi:fv: evex.nds.256.66.0f.w1 c2 /r ib ] AVX512VL,AVX512,FUTURE
VCMPPD kreg|mask,zmmreg,zmmrm512|b64|sae,imm8 [rvmi:fv: evex.nds.512.66.0f.w1 c2 /r ib ] AVX512,FUTURE
@@ -4459,36 +4827,228 @@ VPBROADCASTW ymmreg|mask|z,reg64 [rm: evex.256.66.0f38.w0 7b
VPBROADCASTW zmmreg|mask|z,reg16 [rm: evex.512.66.0f38.w0 7b /r ] AVX512BW,FUTURE
VPBROADCASTW zmmreg|mask|z,reg32 [rm: evex.512.66.0f38.w0 7b /r ] AVX512BW,FUTURE
VPBROADCASTW zmmreg|mask|z,reg64 [rm: evex.512.66.0f38.w0 7b /r ] AVX512BW,FUTURE
+VPCMPEQB kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w0 3f /r 00 ] AVX512VL,AVX512BW,FUTURE
+VPCMPEQB kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w0 3f /r 00 ] AVX512VL,AVX512BW,FUTURE
+VPCMPEQB kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w0 3f /r 00 ] AVX512BW,FUTURE
+VPCMPEQD kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.66.0f3a.w0 1f /r 00 ] AVX512VL,AVX512,FUTURE
+VPCMPEQD kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.66.0f3a.w0 1f /r 00 ] AVX512VL,AVX512,FUTURE
+VPCMPEQD kreg|mask,zmmreg,zmmrm512|b32 [rvmi:fv: evex.nds.512.66.0f3a.w0 1f /r 00 ] AVX512,FUTURE
+VPCMPEQQ kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f3a.w1 1f /r 00 ] AVX512VL,AVX512,FUTURE
+VPCMPEQQ kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f3a.w1 1f /r 00 ] AVX512VL,AVX512,FUTURE
+VPCMPEQQ kreg|mask,zmmreg,zmmrm512|b64 [rvmi:fv: evex.nds.512.66.0f3a.w1 1f /r 00 ] AVX512,FUTURE
+VPCMPEQUB kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w0 3e /r 00 ] AVX512VL,AVX512BW,FUTURE
+VPCMPEQUB kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w0 3e /r 00 ] AVX512VL,AVX512BW,FUTURE
+VPCMPEQUB kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w0 3e /r 00 ] AVX512BW,FUTURE
+VPCMPEQUD kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.66.0f3a.w0 1e /r 00 ] AVX512VL,AVX512,FUTURE
+VPCMPEQUD kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.66.0f3a.w0 1e /r 00 ] AVX512VL,AVX512,FUTURE
+VPCMPEQUD kreg|mask,zmmreg,zmmrm512|b32 [rvmi:fv: evex.nds.512.66.0f3a.w0 1e /r 00 ] AVX512,FUTURE
+VPCMPEQUQ kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f3a.w1 1e /r 00 ] AVX512VL,AVX512,FUTURE
+VPCMPEQUQ kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f3a.w1 1e /r 00 ] AVX512VL,AVX512,FUTURE
+VPCMPEQUQ kreg|mask,zmmreg,zmmrm512|b64 [rvmi:fv: evex.nds.512.66.0f3a.w1 1e /r 00 ] AVX512,FUTURE
+VPCMPEQUW kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w1 3e /r 00 ] AVX512VL,AVX512BW,FUTURE
+VPCMPEQUW kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w1 3e /r 00 ] AVX512VL,AVX512BW,FUTURE
+VPCMPEQUW kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w1 3e /r 00 ] AVX512BW,FUTURE
+VPCMPEQW kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w1 3f /r 00 ] AVX512VL,AVX512BW,FUTURE
+VPCMPEQW kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w1 3f /r 00 ] AVX512VL,AVX512BW,FUTURE
+VPCMPEQW kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w1 3f /r 00 ] AVX512BW,FUTURE
+VPCMPGEB kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w0 3f /r 05 ] AVX512VL,AVX512BW,FUTURE
+VPCMPGEB kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w0 3f /r 05 ] AVX512VL,AVX512BW,FUTURE
+VPCMPGEB kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w0 3f /r 05 ] AVX512BW,FUTURE
+VPCMPGED kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.66.0f3a.w0 1f /r 05 ] AVX512VL,AVX512,FUTURE
+VPCMPGED kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.66.0f3a.w0 1f /r 05 ] AVX512VL,AVX512,FUTURE
+VPCMPGED kreg|mask,zmmreg,zmmrm512|b32 [rvmi:fv: evex.nds.512.66.0f3a.w0 1f /r 05 ] AVX512,FUTURE
+VPCMPGEQ kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f3a.w1 1f /r 05 ] AVX512VL,AVX512,FUTURE
+VPCMPGEQ kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f3a.w1 1f /r 05 ] AVX512VL,AVX512,FUTURE
+VPCMPGEQ kreg|mask,zmmreg,zmmrm512|b64 [rvmi:fv: evex.nds.512.66.0f3a.w1 1f /r 05 ] AVX512,FUTURE
+VPCMPGEUB kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w0 3e /r 05 ] AVX512VL,AVX512BW,FUTURE
+VPCMPGEUB kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w0 3e /r 05 ] AVX512VL,AVX512BW,FUTURE
+VPCMPGEUB kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w0 3e /r 05 ] AVX512BW,FUTURE
+VPCMPGEUD kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.66.0f3a.w0 1e /r 05 ] AVX512VL,AVX512,FUTURE
+VPCMPGEUD kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.66.0f3a.w0 1e /r 05 ] AVX512VL,AVX512,FUTURE
+VPCMPGEUD kreg|mask,zmmreg,zmmrm512|b32 [rvmi:fv: evex.nds.512.66.0f3a.w0 1e /r 05 ] AVX512,FUTURE
+VPCMPGEUQ kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f3a.w1 1e /r 05 ] AVX512VL,AVX512,FUTURE
+VPCMPGEUQ kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f3a.w1 1e /r 05 ] AVX512VL,AVX512,FUTURE
+VPCMPGEUQ kreg|mask,zmmreg,zmmrm512|b64 [rvmi:fv: evex.nds.512.66.0f3a.w1 1e /r 05 ] AVX512,FUTURE
+VPCMPGEUW kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w1 3e /r 05 ] AVX512VL,AVX512BW,FUTURE
+VPCMPGEUW kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w1 3e /r 05 ] AVX512VL,AVX512BW,FUTURE
+VPCMPGEUW kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w1 3e /r 05 ] AVX512BW,FUTURE
+VPCMPGEW kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w1 3f /r 05 ] AVX512VL,AVX512BW,FUTURE
+VPCMPGEW kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w1 3f /r 05 ] AVX512VL,AVX512BW,FUTURE
+VPCMPGEW kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w1 3f /r 05 ] AVX512BW,FUTURE
+VPCMPGTB kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w0 3f /r 06 ] AVX512VL,AVX512BW,FUTURE
+VPCMPGTB kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w0 3f /r 06 ] AVX512VL,AVX512BW,FUTURE
+VPCMPGTB kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w0 3f /r 06 ] AVX512BW,FUTURE
+VPCMPGTD kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.66.0f3a.w0 1f /r 06 ] AVX512VL,AVX512,FUTURE
+VPCMPGTD kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.66.0f3a.w0 1f /r 06 ] AVX512VL,AVX512,FUTURE
+VPCMPGTD kreg|mask,zmmreg,zmmrm512|b32 [rvmi:fv: evex.nds.512.66.0f3a.w0 1f /r 06 ] AVX512,FUTURE
+VPCMPGTQ kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f3a.w1 1f /r 06 ] AVX512VL,AVX512,FUTURE
+VPCMPGTQ kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f3a.w1 1f /r 06 ] AVX512VL,AVX512,FUTURE
+VPCMPGTQ kreg|mask,zmmreg,zmmrm512|b64 [rvmi:fv: evex.nds.512.66.0f3a.w1 1f /r 06 ] AVX512,FUTURE
+VPCMPGTUB kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w0 3e /r 06 ] AVX512VL,AVX512BW,FUTURE
+VPCMPGTUB kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w0 3e /r 06 ] AVX512VL,AVX512BW,FUTURE
+VPCMPGTUB kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w0 3e /r 06 ] AVX512BW,FUTURE
+VPCMPGTUD kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.66.0f3a.w0 1e /r 06 ] AVX512VL,AVX512,FUTURE
+VPCMPGTUD kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.66.0f3a.w0 1e /r 06 ] AVX512VL,AVX512,FUTURE
+VPCMPGTUD kreg|mask,zmmreg,zmmrm512|b32 [rvmi:fv: evex.nds.512.66.0f3a.w0 1e /r 06 ] AVX512,FUTURE
+VPCMPGTUQ kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f3a.w1 1e /r 06 ] AVX512VL,AVX512,FUTURE
+VPCMPGTUQ kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f3a.w1 1e /r 06 ] AVX512VL,AVX512,FUTURE
+VPCMPGTUQ kreg|mask,zmmreg,zmmrm512|b64 [rvmi:fv: evex.nds.512.66.0f3a.w1 1e /r 06 ] AVX512,FUTURE
+VPCMPGTUW kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w1 3e /r 06 ] AVX512VL,AVX512BW,FUTURE
+VPCMPGTUW kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w1 3e /r 06 ] AVX512VL,AVX512BW,FUTURE
+VPCMPGTUW kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w1 3e /r 06 ] AVX512BW,FUTURE
+VPCMPGTW kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w1 3f /r 06 ] AVX512VL,AVX512BW,FUTURE
+VPCMPGTW kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w1 3f /r 06 ] AVX512VL,AVX512BW,FUTURE
+VPCMPGTW kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w1 3f /r 06 ] AVX512BW,FUTURE
+VPCMPLEB kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w0 3f /r 02 ] AVX512VL,AVX512BW,FUTURE
+VPCMPLEB kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w0 3f /r 02 ] AVX512VL,AVX512BW,FUTURE
+VPCMPLEB kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w0 3f /r 02 ] AVX512BW,FUTURE
+VPCMPLED kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.66.0f3a.w0 1f /r 02 ] AVX512VL,AVX512,FUTURE
+VPCMPLED kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.66.0f3a.w0 1f /r 02 ] AVX512VL,AVX512,FUTURE
+VPCMPLED kreg|mask,zmmreg,zmmrm512|b32 [rvmi:fv: evex.nds.512.66.0f3a.w0 1f /r 02 ] AVX512,FUTURE
+VPCMPLEQ kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f3a.w1 1f /r 02 ] AVX512VL,AVX512,FUTURE
+VPCMPLEQ kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f3a.w1 1f /r 02 ] AVX512VL,AVX512,FUTURE
+VPCMPLEQ kreg|mask,zmmreg,zmmrm512|b64 [rvmi:fv: evex.nds.512.66.0f3a.w1 1f /r 02 ] AVX512,FUTURE
+VPCMPLEUB kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w0 3e /r 02 ] AVX512VL,AVX512BW,FUTURE
+VPCMPLEUB kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w0 3e /r 02 ] AVX512VL,AVX512BW,FUTURE
+VPCMPLEUB kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w0 3e /r 02 ] AVX512BW,FUTURE
+VPCMPLEUD kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.66.0f3a.w0 1e /r 02 ] AVX512VL,AVX512,FUTURE
+VPCMPLEUD kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.66.0f3a.w0 1e /r 02 ] AVX512VL,AVX512,FUTURE
+VPCMPLEUD kreg|mask,zmmreg,zmmrm512|b32 [rvmi:fv: evex.nds.512.66.0f3a.w0 1e /r 02 ] AVX512,FUTURE
+VPCMPLEUQ kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f3a.w1 1e /r 02 ] AVX512VL,AVX512,FUTURE
+VPCMPLEUQ kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f3a.w1 1e /r 02 ] AVX512VL,AVX512,FUTURE
+VPCMPLEUQ kreg|mask,zmmreg,zmmrm512|b64 [rvmi:fv: evex.nds.512.66.0f3a.w1 1e /r 02 ] AVX512,FUTURE
+VPCMPLEUW kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w1 3e /r 02 ] AVX512VL,AVX512BW,FUTURE
+VPCMPLEUW kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w1 3e /r 02 ] AVX512VL,AVX512BW,FUTURE
+VPCMPLEUW kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w1 3e /r 02 ] AVX512BW,FUTURE
+VPCMPLEW kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w1 3f /r 02 ] AVX512VL,AVX512BW,FUTURE
+VPCMPLEW kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w1 3f /r 02 ] AVX512VL,AVX512BW,FUTURE
+VPCMPLEW kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w1 3f /r 02 ] AVX512BW,FUTURE
+VPCMPLTB kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w0 3f /r 01 ] AVX512VL,AVX512BW,FUTURE
+VPCMPLTB kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w0 3f /r 01 ] AVX512VL,AVX512BW,FUTURE
+VPCMPLTB kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w0 3f /r 01 ] AVX512BW,FUTURE
+VPCMPLTD kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.66.0f3a.w0 1f /r 01 ] AVX512VL,AVX512,FUTURE
+VPCMPLTD kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.66.0f3a.w0 1f /r 01 ] AVX512VL,AVX512,FUTURE
+VPCMPLTD kreg|mask,zmmreg,zmmrm512|b32 [rvmi:fv: evex.nds.512.66.0f3a.w0 1f /r 01 ] AVX512,FUTURE
+VPCMPLTQ kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f3a.w1 1f /r 01 ] AVX512VL,AVX512,FUTURE
+VPCMPLTQ kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f3a.w1 1f /r 01 ] AVX512VL,AVX512,FUTURE
+VPCMPLTQ kreg|mask,zmmreg,zmmrm512|b64 [rvmi:fv: evex.nds.512.66.0f3a.w1 1f /r 01 ] AVX512,FUTURE
+VPCMPLTUB kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w0 3e /r 01 ] AVX512VL,AVX512BW,FUTURE
+VPCMPLTUB kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w0 3e /r 01 ] AVX512VL,AVX512BW,FUTURE
+VPCMPLTUB kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w0 3e /r 01 ] AVX512BW,FUTURE
+VPCMPLTUD kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.66.0f3a.w0 1e /r 01 ] AVX512VL,AVX512,FUTURE
+VPCMPLTUD kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.66.0f3a.w0 1e /r 01 ] AVX512VL,AVX512,FUTURE
+VPCMPLTUD kreg|mask,zmmreg,zmmrm512|b32 [rvmi:fv: evex.nds.512.66.0f3a.w0 1e /r 01 ] AVX512,FUTURE
+VPCMPLTUQ kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f3a.w1 1e /r 01 ] AVX512VL,AVX512,FUTURE
+VPCMPLTUQ kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f3a.w1 1e /r 01 ] AVX512VL,AVX512,FUTURE
+VPCMPLTUQ kreg|mask,zmmreg,zmmrm512|b64 [rvmi:fv: evex.nds.512.66.0f3a.w1 1e /r 01 ] AVX512,FUTURE
+VPCMPLTUW kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w1 3e /r 01 ] AVX512VL,AVX512BW,FUTURE
+VPCMPLTUW kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w1 3e /r 01 ] AVX512VL,AVX512BW,FUTURE
+VPCMPLTUW kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w1 3e /r 01 ] AVX512BW,FUTURE
+VPCMPLTW kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w1 3f /r 01 ] AVX512VL,AVX512BW,FUTURE
+VPCMPLTW kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w1 3f /r 01 ] AVX512VL,AVX512BW,FUTURE
+VPCMPLTW kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w1 3f /r 01 ] AVX512BW,FUTURE
+VPCMPNEQB kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w0 3f /r 04 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNEQB kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w0 3f /r 04 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNEQB kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w0 3f /r 04 ] AVX512BW,FUTURE
+VPCMPNEQD kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.66.0f3a.w0 1f /r 04 ] AVX512VL,AVX512,FUTURE
+VPCMPNEQD kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.66.0f3a.w0 1f /r 04 ] AVX512VL,AVX512,FUTURE
+VPCMPNEQD kreg|mask,zmmreg,zmmrm512|b32 [rvmi:fv: evex.nds.512.66.0f3a.w0 1f /r 04 ] AVX512,FUTURE
+VPCMPNEQQ kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f3a.w1 1f /r 04 ] AVX512VL,AVX512,FUTURE
+VPCMPNEQQ kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f3a.w1 1f /r 04 ] AVX512VL,AVX512,FUTURE
+VPCMPNEQQ kreg|mask,zmmreg,zmmrm512|b64 [rvmi:fv: evex.nds.512.66.0f3a.w1 1f /r 04 ] AVX512,FUTURE
+VPCMPNEQUB kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w0 3e /r 04 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNEQUB kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w0 3e /r 04 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNEQUB kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w0 3e /r 04 ] AVX512BW,FUTURE
+VPCMPNEQUD kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.66.0f3a.w0 1e /r 04 ] AVX512VL,AVX512,FUTURE
+VPCMPNEQUD kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.66.0f3a.w0 1e /r 04 ] AVX512VL,AVX512,FUTURE
+VPCMPNEQUD kreg|mask,zmmreg,zmmrm512|b32 [rvmi:fv: evex.nds.512.66.0f3a.w0 1e /r 04 ] AVX512,FUTURE
+VPCMPNEQUQ kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f3a.w1 1e /r 04 ] AVX512VL,AVX512,FUTURE
+VPCMPNEQUQ kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f3a.w1 1e /r 04 ] AVX512VL,AVX512,FUTURE
+VPCMPNEQUQ kreg|mask,zmmreg,zmmrm512|b64 [rvmi:fv: evex.nds.512.66.0f3a.w1 1e /r 04 ] AVX512,FUTURE
+VPCMPNEQUW kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w1 3e /r 04 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNEQUW kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w1 3e /r 04 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNEQUW kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w1 3e /r 04 ] AVX512BW,FUTURE
+VPCMPNEQW kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w1 3f /r 04 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNEQW kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w1 3f /r 04 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNEQW kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w1 3f /r 04 ] AVX512BW,FUTURE
+VPCMPNGTB kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w0 3f /r 02 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNGTB kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w0 3f /r 02 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNGTB kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w0 3f /r 02 ] AVX512BW,FUTURE
+VPCMPNGTD kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.66.0f3a.w0 1f /r 02 ] AVX512VL,AVX512,FUTURE
+VPCMPNGTD kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.66.0f3a.w0 1f /r 02 ] AVX512VL,AVX512,FUTURE
+VPCMPNGTD kreg|mask,zmmreg,zmmrm512|b32 [rvmi:fv: evex.nds.512.66.0f3a.w0 1f /r 02 ] AVX512,FUTURE
+VPCMPNGTQ kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f3a.w1 1f /r 02 ] AVX512VL,AVX512,FUTURE
+VPCMPNGTQ kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f3a.w1 1f /r 02 ] AVX512VL,AVX512,FUTURE
+VPCMPNGTQ kreg|mask,zmmreg,zmmrm512|b64 [rvmi:fv: evex.nds.512.66.0f3a.w1 1f /r 02 ] AVX512,FUTURE
+VPCMPNGTUB kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w0 3e /r 02 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNGTUB kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w0 3e /r 02 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNGTUB kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w0 3e /r 02 ] AVX512BW,FUTURE
+VPCMPNGTUD kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.66.0f3a.w0 1e /r 02 ] AVX512VL,AVX512,FUTURE
+VPCMPNGTUD kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.66.0f3a.w0 1e /r 02 ] AVX512VL,AVX512,FUTURE
+VPCMPNGTUD kreg|mask,zmmreg,zmmrm512|b32 [rvmi:fv: evex.nds.512.66.0f3a.w0 1e /r 02 ] AVX512,FUTURE
+VPCMPNGTUQ kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f3a.w1 1e /r 02 ] AVX512VL,AVX512,FUTURE
+VPCMPNGTUQ kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f3a.w1 1e /r 02 ] AVX512VL,AVX512,FUTURE
+VPCMPNGTUQ kreg|mask,zmmreg,zmmrm512|b64 [rvmi:fv: evex.nds.512.66.0f3a.w1 1e /r 02 ] AVX512,FUTURE
+VPCMPNGTUW kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w1 3e /r 02 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNGTUW kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w1 3e /r 02 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNGTUW kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w1 3e /r 02 ] AVX512BW,FUTURE
+VPCMPNGTW kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w1 3f /r 02 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNGTW kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w1 3f /r 02 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNGTW kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w1 3f /r 02 ] AVX512BW,FUTURE
+VPCMPNLEB kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w0 3f /r 06 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNLEB kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w0 3f /r 06 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNLEB kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w0 3f /r 06 ] AVX512BW,FUTURE
+VPCMPNLED kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.66.0f3a.w0 1f /r 06 ] AVX512VL,AVX512,FUTURE
+VPCMPNLED kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.66.0f3a.w0 1f /r 06 ] AVX512VL,AVX512,FUTURE
+VPCMPNLED kreg|mask,zmmreg,zmmrm512|b32 [rvmi:fv: evex.nds.512.66.0f3a.w0 1f /r 06 ] AVX512,FUTURE
+VPCMPNLEQ kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f3a.w1 1f /r 06 ] AVX512VL,AVX512,FUTURE
+VPCMPNLEQ kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f3a.w1 1f /r 06 ] AVX512VL,AVX512,FUTURE
+VPCMPNLEQ kreg|mask,zmmreg,zmmrm512|b64 [rvmi:fv: evex.nds.512.66.0f3a.w1 1f /r 06 ] AVX512,FUTURE
+VPCMPNLEUB kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w0 3e /r 06 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNLEUB kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w0 3e /r 06 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNLEUB kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w0 3e /r 06 ] AVX512BW,FUTURE
+VPCMPNLEUD kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.66.0f3a.w0 1e /r 06 ] AVX512VL,AVX512,FUTURE
+VPCMPNLEUD kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.66.0f3a.w0 1e /r 06 ] AVX512VL,AVX512,FUTURE
+VPCMPNLEUD kreg|mask,zmmreg,zmmrm512|b32 [rvmi:fv: evex.nds.512.66.0f3a.w0 1e /r 06 ] AVX512,FUTURE
+VPCMPNLEUQ kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f3a.w1 1e /r 06 ] AVX512VL,AVX512,FUTURE
+VPCMPNLEUQ kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f3a.w1 1e /r 06 ] AVX512VL,AVX512,FUTURE
+VPCMPNLEUQ kreg|mask,zmmreg,zmmrm512|b64 [rvmi:fv: evex.nds.512.66.0f3a.w1 1e /r 06 ] AVX512,FUTURE
+VPCMPNLEUW kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w1 3e /r 06 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNLEUW kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w1 3e /r 06 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNLEUW kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w1 3e /r 06 ] AVX512BW,FUTURE
+VPCMPNLEW kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w1 3f /r 06 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNLEW kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w1 3f /r 06 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNLEW kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w1 3f /r 06 ] AVX512BW,FUTURE
+VPCMPNLTB kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w0 3f /r 05 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNLTB kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w0 3f /r 05 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNLTB kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w0 3f /r 05 ] AVX512BW,FUTURE
+VPCMPNLTD kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.66.0f3a.w0 1f /r 05 ] AVX512VL,AVX512,FUTURE
+VPCMPNLTD kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.66.0f3a.w0 1f /r 05 ] AVX512VL,AVX512,FUTURE
+VPCMPNLTD kreg|mask,zmmreg,zmmrm512|b32 [rvmi:fv: evex.nds.512.66.0f3a.w0 1f /r 05 ] AVX512,FUTURE
+VPCMPNLTQ kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f3a.w1 1f /r 05 ] AVX512VL,AVX512,FUTURE
+VPCMPNLTQ kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f3a.w1 1f /r 05 ] AVX512VL,AVX512,FUTURE
+VPCMPNLTQ kreg|mask,zmmreg,zmmrm512|b64 [rvmi:fv: evex.nds.512.66.0f3a.w1 1f /r 05 ] AVX512,FUTURE
+VPCMPNLTUB kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w0 3e /r 05 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNLTUB kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w0 3e /r 05 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNLTUB kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w0 3e /r 05 ] AVX512BW,FUTURE
+VPCMPNLTUD kreg|mask,xmmreg,xmmrm128|b32 [rvmi:fv: evex.nds.128.66.0f3a.w0 1e /r 05 ] AVX512VL,AVX512,FUTURE
+VPCMPNLTUD kreg|mask,ymmreg,ymmrm256|b32 [rvmi:fv: evex.nds.256.66.0f3a.w0 1e /r 05 ] AVX512VL,AVX512,FUTURE
+VPCMPNLTUD kreg|mask,zmmreg,zmmrm512|b32 [rvmi:fv: evex.nds.512.66.0f3a.w0 1e /r 05 ] AVX512,FUTURE
+VPCMPNLTUQ kreg|mask,xmmreg,xmmrm128|b64 [rvmi:fv: evex.nds.128.66.0f3a.w1 1e /r 05 ] AVX512VL,AVX512,FUTURE
+VPCMPNLTUQ kreg|mask,ymmreg,ymmrm256|b64 [rvmi:fv: evex.nds.256.66.0f3a.w1 1e /r 05 ] AVX512VL,AVX512,FUTURE
+VPCMPNLTUQ kreg|mask,zmmreg,zmmrm512|b64 [rvmi:fv: evex.nds.512.66.0f3a.w1 1e /r 05 ] AVX512,FUTURE
+VPCMPNLTUW kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w1 3e /r 05 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNLTUW kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w1 3e /r 05 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNLTUW kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w1 3e /r 05 ] AVX512BW,FUTURE
+VPCMPNLTW kreg|mask,xmmreg,xmmrm128 [rvmi:fvm: evex.nds.128.66.0f3a.w1 3f /r 05 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNLTW kreg|mask,ymmreg,ymmrm256 [rvmi:fvm: evex.nds.256.66.0f3a.w1 3f /r 05 ] AVX512VL,AVX512BW,FUTURE
+VPCMPNLTW kreg|mask,zmmreg,zmmrm512 [rvmi:fvm: evex.nds.512.66.0f3a.w1 3f /r 05 ] AVX512BW,FUTURE
VPCMPB kreg|mask,xmmreg,xmmrm128,imm8 [rvmi:fvm: evex.nds.128.66.0f3a.w0 3f /r ib ] AVX512VL,AVX512BW,FUTURE
VPCMPB kreg|mask,ymmreg,ymmrm256,imm8 [rvmi:fvm: evex.nds.256.66.0f3a.w0 3f /r ib ] AVX512VL,AVX512BW,FUTURE
VPCMPB kreg|mask,zmmreg,zmmrm512,imm8 [rvmi:fvm: evex.nds.512.66.0f3a.w0 3f /r ib ] AVX512BW,FUTURE
VPCMPD kreg|mask,xmmreg,xmmrm128|b32,imm8 [rvmi:fv: evex.nds.128.66.0f3a.w0 1f /r ib ] AVX512VL,AVX512,FUTURE
VPCMPD kreg|mask,ymmreg,ymmrm256|b32,imm8 [rvmi:fv: evex.nds.256.66.0f3a.w0 1f /r ib ] AVX512VL,AVX512,FUTURE
VPCMPD kreg|mask,zmmreg,zmmrm512|b32,imm8 [rvmi:fv: evex.nds.512.66.0f3a.w0 1f /r ib ] AVX512,FUTURE
-VPCMPEQB kreg|mask,xmmreg,xmmrm128 [rvm:fvm: evex.nds.128.66.0f.wig 74 /r ] AVX512VL,AVX512BW,FUTURE
-VPCMPEQB kreg|mask,ymmreg,ymmrm256 [rvm:fvm: evex.nds.256.66.0f.wig 74 /r ] AVX512VL,AVX512BW,FUTURE
-VPCMPEQB kreg|mask,zmmreg,zmmrm512 [rvm:fvm: evex.nds.512.66.0f.wig 74 /r ] AVX512BW,FUTURE
-VPCMPEQD kreg|mask,xmmreg,xmmrm128|b32 [rvm:fv: evex.nds.128.66.0f.w0 76 /r ] AVX512VL,AVX512,FUTURE
-VPCMPEQD kreg|mask,ymmreg,ymmrm256|b32 [rvm:fv: evex.nds.256.66.0f.w0 76 /r ] AVX512VL,AVX512,FUTURE
-VPCMPEQD kreg|mask,zmmreg,zmmrm512|b32 [rvm:fv: evex.nds.512.66.0f.w0 76 /r ] AVX512,FUTURE
-VPCMPEQQ kreg|mask,xmmreg,xmmrm128|b64 [rvm:fv: evex.nds.128.66.0f38.w1 29 /r ] AVX512VL,AVX512,FUTURE
-VPCMPEQQ kreg|mask,ymmreg,ymmrm256|b64 [rvm:fv: evex.nds.256.66.0f38.w1 29 /r ] AVX512VL,AVX512,FUTURE
-VPCMPEQQ kreg|mask,zmmreg,zmmrm512|b64 [rvm:fv: evex.nds.512.66.0f38.w1 29 /r ] AVX512,FUTURE
-VPCMPEQW kreg|mask,xmmreg,xmmrm128 [rvm:fvm: evex.nds.128.66.0f.wig 75 /r ] AVX512VL,AVX512BW,FUTURE
-VPCMPEQW kreg|mask,ymmreg,ymmrm256 [rvm:fvm: evex.nds.256.66.0f.wig 75 /r ] AVX512VL,AVX512BW,FUTURE
-VPCMPEQW kreg|mask,zmmreg,zmmrm512 [rvm:fvm: evex.nds.512.66.0f.wig 75 /r ] AVX512BW,FUTURE
-VPCMPGTB kreg|mask,xmmreg,xmmrm128 [rvm:fvm: evex.nds.128.66.0f.wig 64 /r ] AVX512VL,AVX512BW,FUTURE
-VPCMPGTB kreg|mask,ymmreg,ymmrm256 [rvm:fvm: evex.nds.256.66.0f.wig 64 /r ] AVX512VL,AVX512BW,FUTURE
-VPCMPGTB kreg|mask,zmmreg,zmmrm512 [rvm:fvm: evex.nds.512.66.0f.wig 64 /r ] AVX512BW,FUTURE
-VPCMPGTD kreg|mask,xmmreg,xmmrm128|b32 [rvm:fv: evex.nds.128.66.0f.w0 66 /r ] AVX512VL,AVX512,FUTURE
-VPCMPGTD kreg|mask,ymmreg,ymmrm256|b32 [rvm:fv: evex.nds.256.66.0f.w0 66 /r ] AVX512VL,AVX512,FUTURE
-VPCMPGTD kreg|mask,zmmreg,zmmrm512|b32 [rvm:fv: evex.nds.512.66.0f.w0 66 /r ] AVX512,FUTURE
-VPCMPGTQ kreg|mask,xmmreg,xmmrm128|b64 [rvm:fv: evex.nds.128.66.0f38.w1 37 /r ] AVX512VL,AVX512,FUTURE
-VPCMPGTQ kreg|mask,ymmreg,ymmrm256|b64 [rvm:fv: evex.nds.256.66.0f38.w1 37 /r ] AVX512VL,AVX512,FUTURE
-VPCMPGTQ kreg|mask,zmmreg,zmmrm512|b64 [rvm:fv: evex.nds.512.66.0f38.w1 37 /r ] AVX512,FUTURE
-VPCMPGTW kreg|mask,xmmreg,xmmrm128 [rvm:fvm: evex.nds.128.66.0f.wig 65 /r ] AVX512VL,AVX512BW,FUTURE
-VPCMPGTW kreg|mask,ymmreg,ymmrm256 [rvm:fvm: evex.nds.256.66.0f.wig 65 /r ] AVX512VL,AVX512BW,FUTURE
-VPCMPGTW kreg|mask,zmmreg,zmmrm512 [rvm:fvm: evex.nds.512.66.0f.wig 65 /r ] AVX512BW,FUTURE
VPCMPQ kreg|mask,xmmreg,xmmrm128|b64,imm8 [rvmi:fv: evex.nds.128.66.0f3a.w1 1f /r ib ] AVX512VL,AVX512,FUTURE
VPCMPQ kreg|mask,ymmreg,ymmrm256|b64,imm8 [rvmi:fv: evex.nds.256.66.0f3a.w1 1f /r ib ] AVX512VL,AVX512,FUTURE
VPCMPQ kreg|mask,zmmreg,zmmrm512|b64,imm8 [rvmi:fv: evex.nds.512.66.0f3a.w1 1f /r ib ] AVX512,FUTURE
@@ -5284,13 +5844,13 @@ MOVDIRI mem32,reg32 [mr: np 0f 38 f9 /r] FUTURE,SD
MOVDIRI mem64,reg64 [mr: o64 0f 38 f9 /r] FUTURE,X64,SQ
MOVDIR64B reg16,mem512 [rm: a16 66 0f 38 f8 /r] FUTURE,NOLONG
MOVDIR64B reg32,mem512 [rm: a32 66 0f 38 f8 /r] FUTURE
-MOVDIR64B reg64,mem512 [rm: a64 66 0f 38 f8 /r] FUTURE,X64
+MOVDIR64B reg64,mem512 [rm: o64nw a64 66 0f 38 f8 /r] FUTURE,X64
PCONFIG void [ np 0f 01 c5] FUTURE
TPAUSE reg32 [m: 66 0f ae /6] FUTURE
TPAUSE reg32,reg_edx,reg_eax [m--: 66 0f ae /6] FUTURE,ND
UMONITOR reg16 [m: a16 f3 0f ae /6] FUTURE,NOLONG
UMONITOR reg32 [m: a32 f3 0f ae /6] FUTURE
-UMONITOR reg64 [m: a64 f3 0f ae /6] FUTURE,X64
+UMONITOR reg64 [m: o64nw a64 f3 0f ae /6] FUTURE,X64
UMWAIT reg32 [m: f2 0f ae /6] FUTURE
UMWAIT reg32,reg_edx,reg_eax [m--: f2 0f ae /6] FUTURE,ND
WBNOINVD void [ f3 0f 09] FUTURE
@@ -5349,15 +5909,15 @@ VPSHLDD zmmreg|mask|z,zmmreg*,zmmrm512|b32,imm8 [rvmi:fv: evex.nds.512.66.0f3a
VPSHLDQ xmmreg|mask|z,xmmreg*,xmmrm128|b64,imm8 [rvmi:fv: evex.nds.128.66.0f3a.w1 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHLDQ ymmreg|mask|z,ymmreg*,ymmrm256|b64,imm8 [rvmi:fv: evex.nds.256.66.0f3a.w1 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHLDQ zmmreg|mask|z,zmmreg*,zmmrm512|b64,imm8 [rvmi:fv: evex.nds.512.66.0f3a.w1 71 /r ib] AVX512VBMI2,FUTURE
-VPSHLDVW xmmreg|mask|z,xmmreg*,xmmrm128 [rvmi:fvm: evex.dds.128.66.0f38.w1 70 /r ib] AVX512VBMI2,AVX512VL,FUTURE
-VPSHLDVW ymmreg|mask|z,ymmreg*,ymmrm256 [rvmi:fvm: evex.dds.256.66.0f38.w1 70 /r ib] AVX512VBMI2,AVX512VL,FUTURE
-VPSHLDVW zmmreg|mask|z,zmmreg*,zmmrm512 [rvmi:fvm: evex.dds.512.66.0f38.w1 70 /r ib] AVX512VBMI2,FUTURE
-VPSHLDVD xmmreg|mask|z,xmmreg*,xmmrm128|b32 [rvmi:fv: evex.dds.128.66.0f38.w0 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE
-VPSHLDVD ymmreg|mask|z,ymmreg*,ymmrm256|b32 [rvmi:fv: evex.dds.256.66.0f38.w0 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE
-VPSHLDVD zmmreg|mask|z,zmmreg*,zmmrm512|b32 [rvmi:fv: evex.dds.512.66.0f38.w0 71 /r ib] AVX512VBMI2,FUTURE
-VPSHLDVQ xmmreg|mask|z,xmmreg*,xmmrm128|b64 [rvmi:fv: evex.dds.128.66.0f38.w1 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE
-VPSHLDVQ ymmreg|mask|z,ymmreg*,ymmrm256|b64 [rvmi:fv: evex.dds.256.66.0f38.w1 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE
-VPSHLDVQ zmmreg|mask|z,zmmreg*,zmmrm512|b64 [rvmi:fv: evex.dds.512.66.0f38.w1 71 /r ib] AVX512VBMI2,FUTURE
+VPSHLDVW xmmreg|mask|z,xmmreg*,xmmrm128 [rvmi:fvm: evex.dds.128.66.0f38.w1 70 /r] AVX512VBMI2,AVX512VL,FUTURE
+VPSHLDVW ymmreg|mask|z,ymmreg*,ymmrm256 [rvmi:fvm: evex.dds.256.66.0f38.w1 70 /r] AVX512VBMI2,AVX512VL,FUTURE
+VPSHLDVW zmmreg|mask|z,zmmreg*,zmmrm512 [rvmi:fvm: evex.dds.512.66.0f38.w1 70 /r] AVX512VBMI2,FUTURE
+VPSHLDVD xmmreg|mask|z,xmmreg*,xmmrm128|b32 [rvmi:fv: evex.dds.128.66.0f38.w0 71 /r] AVX512VBMI2,AVX512VL,FUTURE
+VPSHLDVD ymmreg|mask|z,ymmreg*,ymmrm256|b32 [rvmi:fv: evex.dds.256.66.0f38.w0 71 /r] AVX512VBMI2,AVX512VL,FUTURE
+VPSHLDVD zmmreg|mask|z,zmmreg*,zmmrm512|b32 [rvmi:fv: evex.dds.512.66.0f38.w0 71 /r] AVX512VBMI2,FUTURE
+VPSHLDVQ xmmreg|mask|z,xmmreg*,xmmrm128|b64 [rvmi:fv: evex.dds.128.66.0f38.w1 71 /r] AVX512VBMI2,AVX512VL,FUTURE
+VPSHLDVQ ymmreg|mask|z,ymmreg*,ymmrm256|b64 [rvmi:fv: evex.dds.256.66.0f38.w1 71 /r] AVX512VBMI2,AVX512VL,FUTURE
+VPSHLDVQ zmmreg|mask|z,zmmreg*,zmmrm512|b64 [rvmi:fv: evex.dds.512.66.0f38.w1 71 /r] AVX512VBMI2,FUTURE
VPSHRDW xmmreg|mask|z,xmmreg*,xmmrm128,imm8 [rvmi:fvm: evex.nds.128.66.0f3a.w1 72 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHRDW ymmreg|mask|z,ymmreg*,ymmrm256,imm8 [rvmi:fvm: evex.nds.256.66.0f3a.w1 72 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHRDW zmmreg|mask|z,zmmreg*,zmmrm512,imm8 [rvmi:fvm: evex.nds.512.66.0f3a.w1 72 /r ib] AVX512VBMI2,FUTURE
@@ -5367,15 +5927,15 @@ VPSHRDD zmmreg|mask|z,zmmreg*,zmmrm512|b32,imm8 [rvmi:fv: evex.nds.512.66.0f3a
VPSHRDQ xmmreg|mask|z,xmmreg*,xmmrm128|b64,imm8 [rvmi:fv: evex.nds.128.66.0f3a.w1 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHRDQ ymmreg|mask|z,ymmreg*,ymmrm256|b64,imm8 [rvmi:fv: evex.nds.256.66.0f3a.w1 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHRDQ zmmreg|mask|z,zmmreg*,zmmrm512|b64,imm8 [rvmi:fv: evex.nds.512.66.0f3a.w1 73 /r ib] AVX512VBMI2,FUTURE
-VPSHRDVW xmmreg|mask|z,xmmreg*,xmmrm128 [rvmi:fvm: evex.dds.128.66.0f38.w1 72 /r ib] AVX512VBMI2,AVX512VL,FUTURE
-VPSHRDVW ymmreg|mask|z,ymmreg*,ymmrm256 [rvmi:fvm: evex.dds.256.66.0f38.w1 72 /r ib] AVX512VBMI2,AVX512VL,FUTURE
-VPSHRDVW zmmreg|mask|z,zmmreg*,zmmrm512 [rvmi:fvm: evex.dds.512.66.0f38.w1 72 /r ib] AVX512VBMI2,FUTURE
-VPSHRDVD xmmreg|mask|z,xmmreg*,xmmrm128|b32 [rvmi:fv: evex.dds.128.66.0f38.w0 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE
-VPSHRDVD ymmreg|mask|z,ymmreg*,ymmrm256|b32 [rvmi:fv: evex.dds.256.66.0f38.w0 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE
-VPSHRDVD zmmreg|mask|z,zmmreg*,zmmrm512|b32 [rvmi:fv: evex.dds.512.66.0f38.w0 73 /r ib] AVX512VBMI2,FUTURE
-VPSHRDVQ xmmreg|mask|z,xmmreg*,xmmrm128|b64 [rvmi:fv: evex.dds.128.66.0f38.w1 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE
-VPSHRDVQ ymmreg|mask|z,ymmreg*,ymmrm256|b64 [rvmi:fv: evex.dds.256.66.0f38.w1 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE
-VPSHRDVQ zmmreg|mask|z,zmmreg*,zmmrm512|b64 [rvmi:fv: evex.dds.512.66.0f38.w1 73 /r ib] AVX512VBMI2,FUTURE
+VPSHRDVW xmmreg|mask|z,xmmreg*,xmmrm128 [rvmi:fvm: evex.dds.128.66.0f38.w1 72 /r] AVX512VBMI2,AVX512VL,FUTURE
+VPSHRDVW ymmreg|mask|z,ymmreg*,ymmrm256 [rvmi:fvm: evex.dds.256.66.0f38.w1 72 /r] AVX512VBMI2,AVX512VL,FUTURE
+VPSHRDVW zmmreg|mask|z,zmmreg*,zmmrm512 [rvmi:fvm: evex.dds.512.66.0f38.w1 72 /r] AVX512VBMI2,FUTURE
+VPSHRDVD xmmreg|mask|z,xmmreg*,xmmrm128|b32 [rvmi:fv: evex.dds.128.66.0f38.w0 73 /r] AVX512VBMI2,AVX512VL,FUTURE
+VPSHRDVD ymmreg|mask|z,ymmreg*,ymmrm256|b32 [rvmi:fv: evex.dds.256.66.0f38.w0 73 /r] AVX512VBMI2,AVX512VL,FUTURE
+VPSHRDVD zmmreg|mask|z,zmmreg*,zmmrm512|b32 [rvmi:fv: evex.dds.512.66.0f38.w0 73 /r] AVX512VBMI2,FUTURE
+VPSHRDVQ xmmreg|mask|z,xmmreg*,xmmrm128|b64 [rvmi:fv: evex.dds.128.66.0f38.w1 73 /r] AVX512VBMI2,AVX512VL,FUTURE
+VPSHRDVQ ymmreg|mask|z,ymmreg*,ymmrm256|b64 [rvmi:fv: evex.dds.256.66.0f38.w1 73 /r] AVX512VBMI2,AVX512VL,FUTURE
+VPSHRDVQ zmmreg|mask|z,zmmreg*,zmmrm512|b64 [rvmi:fv: evex.dds.512.66.0f38.w1 73 /r] AVX512VBMI2,FUTURE
;# AVX512 VNNI
VPDPBUSD xmmreg|mask|z,xmmreg*,xmmrm128|b32 [rvm:fv: evex.dds.128.66.0f38.w0 50 /r] AVX512VNNI,AVX512VL,FUTURE
@@ -5423,6 +5983,22 @@ ENCLS void [ np 0f 01 cf] SGX,FUTURE
ENCLU void [ np 0f 01 d7] SGX,FUTURE
ENCLV void [ np 0f 01 c0] SGX,FUTURE
+;# Intel Control-Flow Enforcement Technology (CET)
+CLRSSBSY mem64 [m: f3 0f ae /6] CET,FUTURE
+ENDBR32 void [ f3 0f 1e fb] CET,FUTURE
+ENDBR64 void [ f3 0f 1e fa] CET,FUTURE
+INCSSPD reg32 [m: o32 f3 0f ae /5] CET,FUTURE
+INCSSPQ reg64 [m: o64 f3 0f ae /5] CET,FUTURE,X64
+RDSSPD reg32 [m: o32 f3 0f 1e /1] CET,FUTURE
+RDSSPQ reg64 [m: o64 f3 0f 1e /1] CET,FUTURE,X64
+RSTORSSP mem64 [m: f3 0f 01 /5] CET,FUTURE
+SAVEPREVSSP void [ f3 0f 01 ea] CET,FUTURE
+SETSSBSY void [ f3 0f 01 e8] CET,FUTURE
+WRUSSD mem,reg32 [mr: o32 66 0f 38 f5 /r] CET,FUTURE
+WRUSSQ mem,reg64 [mr: o64 66 0f 38 f5 /r] CET,FUTURE,X64
+WRSSD mem,reg32 [mr: o32 0f 38 f6 /r] CET,FUTURE
+WRSSQ mem,reg64 [mr: o64 0f 38 f6 /r] CET,FUTURE,X64
+
;# Systematic names for the hinting nop instructions
; These should be last in the file
HINT_NOP0 rm16 [m: o16 0f 18 /0] P6,UNDOC