Merge tag 'nasm-2.15.04'

NASM 2.15.04

Conflicts:
	asm/listing.h
	asm/pptok.pl
	asm/preproc.c
	version

This doesn't pass travis test 3392711, which is using an extremely odd
construct of %?? in the middle of an argument sequence for an smacro
while not being in a macro itself, and expecting it to expand to the
macro name. This seems to *really* confuse the master branch.

Resolve this later...
This commit is contained in:
H. Peter Anvin (Intel) 2020-08-25 16:16:09 -07:00
commit cc843efa38
45 changed files with 1244 additions and 734 deletions

View File

@ -65,8 +65,8 @@ LN_S = @LN_S@
FIND = find
# Binary suffixes
O = @OBJEXT@
X = @EXEEXT@
O = @OBJEXT@
X = @EXEEXT@
A = @LIBEXT@
# Debug stuff
@ -97,7 +97,7 @@ endif
$(XMLTO) man --skip-validation $< 2>/dev/null
#-- Begin File Lists --#
NASM = asm/nasm.$(O)
NASM = asm/nasm.$(O)
NDISASM = disasm/ndisasm.$(O)
LIBOBJ = stdlib/snprintf.$(O) stdlib/vsnprintf.$(O) stdlib/strlcpy.$(O) \
@ -146,6 +146,8 @@ LIBOBJ = stdlib/snprintf.$(O) stdlib/vsnprintf.$(O) stdlib/strlcpy.$(O) \
\
disasm/disasm.$(O) disasm/sync.$(O)
ALLOBJ = $(NASM) $(NDISASM) $(LIBOBJ)
SUBDIRS = stdlib nasmlib output asm disasm x86 common macros
XSUBDIRS = test doc nsis rdoff
DEPDIRS = . include config x86 rdoff $(SUBDIRS)
@ -257,21 +259,28 @@ x86/regs.h: x86/regs.dat x86/regs.pl
$(RUNPERL) $(srcdir)/x86/regs.pl h \
$(srcdir)/x86/regs.dat > x86/regs.h
# Extract warnings from source code. Since this depends on
# ALL the source files, this is only done on demand.
# Extract warnings from source code. This is done automatically if any
# C files have changed; the script is fast enough that that is
# reasonable, but doesn't update the time stamp if the files aren't
# changed, to avoid rebuilding everything every time. Track the actual
# dependency by the empty file asm/warnings.time.
WARNFILES = asm/warnings.c include/warnings.h doc/warnings.src
warnings:
$(RM_F) $(WARNFILES)
$(MAKE) asm/warnings.time
asm/warnings.time: $(ALLOBJ:.@OBJEXT@=.c)
: > asm/warnings.time
$(MAKE) $(WARNFILES)
asm/warnings.c: asm/warnings.pl
asm/warnings.c: asm/warnings.pl asm/warnings.time
$(RUNPERL) $(srcdir)/asm/warnings.pl c asm/warnings.c $(srcdir)
include/warnings.h: asm/warnings.pl
include/warnings.h: asm/warnings.pl asm/warnings.time
$(RUNPERL) $(srcdir)/asm/warnings.pl h include/warnings.h $(srcdir)
doc/warnings.src: asm/warnings.pl
doc/warnings.src: asm/warnings.pl asm/warnings.time
$(RUNPERL) $(srcdir)/asm/warnings.pl doc doc/warnings.src $(srcdir)
# Assembler token hash
@ -402,12 +411,12 @@ distclean: clean
done
$(RM_F) test/*.$(O)
$(RM_RF) autom4te*.cache
$(RM_F) Makefile *.dep
$(RM_F) Makefile *.dep asm/warnings.time
cleaner: clean
$(RM_F) $(PERLREQ) *.1 nasm.spec
$(MAKE) -C doc clean
$(RM_F) *.dep
$(RM_F) *.dep asm/warnings.time
spotless: distclean cleaner
$(RM_F) doc/Makefile

View File

@ -61,7 +61,7 @@ X = .exe
#-- Begin File Lists --#
# Edit in Makefile.in, not here!
NASM = asm\nasm.$(O)
NASM = asm\nasm.$(O)
NDISASM = disasm\ndisasm.$(O)
LIBOBJ = stdlib\snprintf.$(O) stdlib\vsnprintf.$(O) stdlib\strlcpy.$(O) \
@ -110,6 +110,8 @@ LIBOBJ = stdlib\snprintf.$(O) stdlib\vsnprintf.$(O) stdlib\strlcpy.$(O) \
\
disasm\disasm.$(O) disasm\sync.$(O)
ALLOBJ = $(NASM) $(NDISASM) $(LIBOBJ)
SUBDIRS = stdlib nasmlib output asm disasm x86 common macros
XSUBDIRS = test doc nsis rdoff
DEPDIRS = . include config x86 rdoff $(SUBDIRS)
@ -216,21 +218,28 @@ x86\regs.h: x86\regs.dat x86\regs.pl
$(RUNPERL) $(srcdir)\x86\regs.pl h \
$(srcdir)\x86\regs.dat > x86\regs.h
# Extract warnings from source code. Since this depends on
# ALL the source files, this is only done on demand.
# Extract warnings from source code. This is done automatically if any
# C files have changed; the script is fast enough that that is
# reasonable, but doesn't update the time stamp if the files aren't
# changed, to avoid rebuilding everything every time. Track the actual
# dependency by the empty file asm\warnings.time.
WARNFILES = asm\warnings.c include\warnings.h doc\warnings.src
warnings:
$(RM_F) $(WARNFILES)
$(MAKE) asm\warnings.time
asm\warnings.time: $(ALLOBJ:.@OBJEXT@=.c)
: > asm\warnings.time
$(MAKE) $(WARNFILES)
asm\warnings.c: asm\warnings.pl
asm\warnings.c: asm\warnings.pl asm\warnings.time
$(RUNPERL) $(srcdir)\asm\warnings.pl c asm\warnings.c $(srcdir)
include\warnings.h: asm\warnings.pl
include\warnings.h: asm\warnings.pl asm\warnings.time
$(RUNPERL) $(srcdir)\asm\warnings.pl h include\warnings.h $(srcdir)
doc\warnings.src: asm\warnings.pl
doc\warnings.src: asm\warnings.pl asm\warnings.time
$(RUNPERL) $(srcdir)\asm\warnings.pl doc doc\warnings.src $(srcdir)
# Assembler token hash

View File

@ -50,7 +50,7 @@ X = .exe
#-- Begin File Lists --#
# Edit in Makefile.in, not here!
NASM = asm\nasm.$(O)
NASM = asm\nasm.$(O)
NDISASM = disasm\ndisasm.$(O)
LIBOBJ = stdlib\snprintf.$(O) stdlib\vsnprintf.$(O) stdlib\strlcpy.$(O) &
@ -99,6 +99,8 @@ LIBOBJ = stdlib\snprintf.$(O) stdlib\vsnprintf.$(O) stdlib\strlcpy.$(O) &
&
disasm\disasm.$(O) disasm\sync.$(O)
ALLOBJ = $(NASM) $(NDISASM) $(LIBOBJ)
SUBDIRS = stdlib nasmlib output asm disasm x86 common macros
XSUBDIRS = test doc nsis rdoff
DEPDIRS = . include config x86 rdoff $(SUBDIRS)
@ -229,21 +231,28 @@ x86\regs.h: x86\regs.dat x86\regs.pl
$(RUNPERL) $(srcdir)\x86\regs.pl h &
$(srcdir)\x86\regs.dat > x86\regs.h
# Extract warnings from source code. Since this depends on
# ALL the source files, this is only done on demand.
# Extract warnings from source code. This is done automatically if any
# C files have changed; the script is fast enough that that is
# reasonable, but doesn't update the time stamp if the files aren't
# changed, to avoid rebuilding everything every time. Track the actual
# dependency by the empty file asm\warnings.time.
WARNFILES = asm\warnings.c include\warnings.h doc\warnings.src
warnings:
$(RM_F) $(WARNFILES)
$(MAKE) asm\warnings.time
asm\warnings.time: $(ALLOBJ:.@OBJEXT@=.c)
: > asm\warnings.time
$(MAKE) $(WARNFILES)
asm\warnings.c: asm\warnings.pl
asm\warnings.c: asm\warnings.pl asm\warnings.time
$(RUNPERL) $(srcdir)\asm\warnings.pl c asm\warnings.c $(srcdir)
include\warnings.h: asm\warnings.pl
include\warnings.h: asm\warnings.pl asm\warnings.time
$(RUNPERL) $(srcdir)\asm\warnings.pl h include\warnings.h $(srcdir)
doc\warnings.src: asm\warnings.pl
doc\warnings.src: asm\warnings.pl asm\warnings.time
$(RUNPERL) $(srcdir)\asm\warnings.pl doc doc\warnings.src $(srcdir)
# Assembler token hash

View File

@ -1246,7 +1246,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
enum ea_type eat;
uint8_t hleok = 0;
bool lockcheck = true;
enum reg_enum mib_index = R_none; /* For a separate index MIB reg form */
enum reg_enum mib_index = R_none; /* For a separate index reg form */
const char *errmsg;
ins->rex = 0; /* Ensure REX is reset */
@ -1282,7 +1282,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
break;
case4(014):
/* this is an index reg of MIB operand */
/* this is an index reg of a split SIB operand */
mib_index = opx->basereg;
break;
@ -1612,6 +1612,10 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
}
}
/* SIB encoding required */
if (itemp_has(temp, IF_SIB))
opy->eaflags |= EAF_SIB;
if (process_ea(opy, &ea_data, bits,
rfield, rflags, ins, &errmsg) != eat) {
nasm_nonfatal("%s", errmsg);
@ -2833,9 +2837,8 @@ static enum ea_type process_ea(operand *input, ea *output, int bits,
}
}
if (bits == 64 &&
!(IP_REL & ~input->type) && (eaflags & EAF_MIB)) {
*errmsg = "RIP-relative addressing is prohibited for MIB";
if (bits == 64 && !(IP_REL & ~input->type) && (eaflags & EAF_SIB)) {
*errmsg = "instruction requires SIB encoding, cannot be RIP-relative";
goto err;
}
@ -2844,7 +2847,7 @@ static enum ea_type process_ea(operand *input, ea *output, int bits,
input->disp_size != (addrbits != 16 ? 32 : 16)))
nasm_warn(WARN_OTHER, "displacement size ignored on absolute address");
if ((eaflags & EAF_MIB) || (bits == 64 && (~input->type & IP_REL))) {
if ((eaflags & EAF_SIB) || (bits == 64 && (~input->type & IP_REL))) {
output->sib_present = true;
output->sib = GEN_SIB(0, 4, 5);
output->bytes = 4;
@ -3022,7 +3025,7 @@ static enum ea_type process_ea(operand *input, ea *output, int bits,
bt = it, bx = ix, it = -1, ix = 0;
}
if (eaflags & EAF_MIB) {
/* only for mib operands */
/* MIB/split-SIB encoding */
if (it == -1 && (hb == b && ht == EAH_NOTBASE)) {
/*
* make a single reg index [reg*1].
@ -3063,7 +3066,7 @@ static enum ea_type process_ea(operand *input, ea *output, int bits,
output->rex |= rexflags(it, ix, REX_X);
output->rex |= rexflags(bt, bx, REX_B);
if (it == -1 && (bt & 7) != REG_NUM_ESP && !(eaflags & EAF_MIB)) {
if (it == -1 && (bt & 7) != REG_NUM_ESP && !(eaflags & EAF_SIB)) {
/* no SIB needed */
int mod, rm;

View File

@ -727,7 +727,7 @@ static expr *eval_floatize(enum floatize type)
len = fmt->bytes - fmt->offset;
if (len > 8)
len = 8; /* Max 64 bits */
p = result + len;
p = result + len + fmt->offset;
val = 0;
for (i = len; i; i--) {
p--;

View File

@ -340,7 +340,7 @@ static void list_downlevel(int type)
}
}
static void list_error(errflags severity, const char *fmt, ...)
static void printf_func(2, 3) list_error(errflags severity, const char *fmt, ...)
{
va_list ap;

View File

@ -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.
*
@ -140,9 +140,10 @@ extern uint64_t list_options, active_list_options;
* computation is needed is when parsing the -L option or %pragma list
* options, neither of which is in any way performance critical.
*
* The character + represents ALL listing options.
* The character + represents ALL listing options except -Lw (flush
* after every line.)
*/
static inline const_func uint64_t list_option_mask(unsigned char x)
static inline const_func uint64_t list_option_mask_val(unsigned char x)
{
if (x >= 'a') {
if (x > 'z')
@ -156,8 +157,6 @@ static inline const_func uint64_t list_option_mask(unsigned char x)
if (x > '9')
return 0;
x = x - '0' + 2 + 26*2;
} else if (x == '+') {
return ~UINT64_C(1);
} else {
return 0;
}
@ -165,6 +164,14 @@ static inline const_func uint64_t list_option_mask(unsigned char x)
return UINT64_C(1) << x;
}
static inline const_func uint64_t list_option_mask(unsigned char x)
{
if (x == '+')
return ~(list_option_mask_val('w') | 3);
else
return list_option_mask_val(x);
}
/* Return true if the listing engine is active and a certain option is set. */
static inline pure_func bool list_option(unsigned char x)
{

View File

@ -2263,8 +2263,8 @@ 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"
" -Lw flush the output after every line (very slow!)\n"
" -L+ enable all listing options except -Lw (very verbose!)\n"
"\n"
" -Oflags... optimize opcodes, immediates and branch offsets\n"
" -O0 no optimization\n"

View File

@ -458,11 +458,17 @@ static int parse_eops(extop **result, bool critical, int elem)
/* 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);
/*
* Subexpression is a single element, flatten.
* Note that if subexpr has an allocated buffer associated
* with it, freeing it would free the buffer, too, so
* we need to move subexpr up, not eop down.
*/
if (!subexpr->elem)
subexpr->elem = eop->elem;
subexpr->dup *= eop->dup;
nasm_free(eop);
eop = subexpr;
} else {
eop->type = EOT_EXTOP;
}

View File

@ -1347,6 +1347,11 @@ static Token *tokenize(const char *line)
p++;
if (*p == '?')
p++;
} else if (*p == '*' && p[1] == '?') {
/* %*? and %*?? */
p += 2;
if (*p == '?')
p++;
} else if (*p == '!') {
/* Environment variable reference */
p++;
@ -1407,6 +1412,16 @@ static Token *tokenize(const char *line)
type = TOKEN_PREPROC_ID;
break;
case '*':
type = TOKEN_OTHER;
if (line[2] == '?') {
if (toklen == 3)
type = TOKEN_PREPROC_SQ;
else if (toklen == 4 && line[3] == '?')
type = TOKEN_PREPROC_SQQ;
}
break;
case '!':
type = (toklen == 2) ? TOKEN_OTHER : TOKEN_ENVIRON;
break;
@ -2335,9 +2350,8 @@ restart:
continue;
}
}
if (defn) {
*defn = (nparam == m->nparam || nparam == -1) ? m : NULL;
}
if (defn)
*defn = m;
return true;
}
m = m->next;
@ -2986,7 +3000,8 @@ static SMacro *define_smacro(const char *mname, bool casesense,
struct hash_table *smtbl;
Context *ctx;
bool defining_alias = false;
unsigned int nparam = 0;
int nparam = 0;
bool defined;
if (tmpl) {
defining_alias = tmpl->alias;
@ -2995,46 +3010,99 @@ static SMacro *define_smacro(const char *mname, bool casesense,
mark_smac_params(expansion, tmpl, 0);
}
while (1) {
ctx = get_ctx(mname, &mname);
ctx = get_ctx(mname, &mname);
if (!smacro_defined(ctx, mname, nparam, &smac, casesense, true)) {
/* Create a new macro */
smtbl = ctx ? &ctx->localmac : &smacros;
smhead = (SMacro **) hash_findi_add(smtbl, mname);
nasm_new(smac);
smac->next = *smhead;
*smhead = smac;
break;
} else if (!smac) {
nasm_warn(WARN_OTHER, "single-line macro `%s' defined both with and"
" without parameters", mname);
/*
* Some instances of the old code considered this a failure,
* some others didn't. What is the right thing to do here?
*/
goto fail;
} else if (!smac->alias || ppconf.noaliases || defining_alias) {
/*
* We're redefining, so we have to take over an
* existing SMacro structure. This means freeing
* what was already in it, but not the structure itself.
*/
clear_smacro(smac);
break;
} else if (smac->in_progress) {
nasm_nonfatal("macro alias loop");
goto fail;
} else {
/* It is an alias macro; follow the alias link */
SMacro *s;
defined = smacro_defined(ctx, mname, nparam, &smac, casesense, true);
smac->in_progress = true;
s = define_smacro(tok_text(smac->expansion), casesense,
expansion, tmpl);
smac->in_progress = false;
return s;
if (defined) {
if (smac->alias) {
if (smac->in_progress) {
nasm_nonfatal("macro alias loop");
goto fail;
}
if (!defining_alias && !ppconf.noaliases) {
/* It is an alias macro; follow the alias link */
SMacro *s;
smac->in_progress = true;
s = define_smacro(tok_text(smac->expansion), casesense,
expansion, tmpl);
smac->in_progress = false;
return s;
}
}
if (casesense ^ smac->casesense) {
/*
*!macro-def-case-single [on] single-line macro defined both case sensitive and insensitive
*! warns when a single-line macro is defined both case
*! sensitive and case insensitive.
*! The new macro
*! definition will override (shadow) the original one,
*! although the original macro is not deleted, and will
*! be re-exposed if the new macro is deleted with
*! \c{%undef}, or, if the original macro is the case
*! insensitive one, the macro call is done with a
*! different case.
*/
nasm_warn(WARN_MACRO_DEF_CASE_SINGLE, "case %ssensitive definition of macro `%s' will shadow %ssensitive macro `%s'",
casesense ? "" : "in",
mname,
smac->casesense ? "" : "in",
smac->name);
defined = false;
} else if ((!!nparam) ^ (!!smac->nparam)) {
/*
* Most recent versions of NASM considered this an error,
* so promote this warning to error by default.
*
*!macro-def-param-single [err] single-line macro defined with and without parameters
*! warns if the same single-line macro is defined with and
*! without parameters.
*! The new macro
*! definition will override (shadow) the original one,
*! although the original macro is not deleted, and will
*! be re-exposed if the new macro is deleted with
*! \c{%undef}.
*/
nasm_warn(WARN_MACRO_DEF_PARAM_SINGLE,
"macro `%s' defined both with and without parameters",
mname);
defined = false;
} else if (smac->nparam < nparam) {
/*
*!macro-def-greedy-single [on] single-line macro
*! definition shadows greedy macro warns when a
*! single-line macro is defined which would match a
*! previously existing greedy definition. The new macro
*! definition will override (shadow) the original one,
*! although the original macro is not deleted, and will
*! be re-exposed if the new macro is deleted with
*! \c{%undef}, and will be invoked if called with a
*! parameter count that does not match the new definition.
*/
nasm_warn(WARN_MACRO_DEF_GREEDY_SINGLE,
"defining macro `%s' shadows previous greedy definition",
mname);
defined = false;
}
}
if (defined) {
/*
* We're redefinining, so we have to take over an
* existing SMacro structure. This means freeing
* what was already in it, but not the structure itself.
*/
clear_smacro(smac);
} else {
/* Create a new macro */
smtbl = ctx ? &ctx->localmac : &smacros;
smhead = (SMacro **) hash_findi_add(smtbl, mname);
nasm_new(smac);
smac->next = *smhead;
*smhead = smac;
}
smac->name = nasm_strdup(mname);
@ -3660,6 +3728,9 @@ static int do_directive(Token *tline, Token **output)
break;
case PP_STACKSIZE:
{
const char *arg;
/* Directive to tell NASM what the default stack size is. The
* default is for a 16-bit stack, and this can be overriden with
* %stacksize large.
@ -3667,20 +3738,24 @@ static int do_directive(Token *tline, Token **output)
tline = skip_white(tline->next);
if (!tline || tline->type != TOKEN_ID) {
nasm_nonfatal("`%s' missing size parameter", dname);
break;
}
if (nasm_stricmp(tok_text(tline), "flat") == 0) {
arg = tok_text(tline);
if (nasm_stricmp(arg, "flat") == 0) {
/* All subsequent ARG directives are for a 32-bit stack */
StackSize = 4;
StackPointer = "ebp";
ArgOffset = 8;
LocalOffset = 0;
} else if (nasm_stricmp(tok_text(tline), "flat64") == 0) {
} else if (nasm_stricmp(arg, "flat64") == 0) {
/* All subsequent ARG directives are for a 64-bit stack */
StackSize = 8;
StackPointer = "rbp";
ArgOffset = 16;
LocalOffset = 0;
} else if (nasm_stricmp(tok_text(tline), "large") == 0) {
} else if (nasm_stricmp(arg, "large") == 0) {
/* All subsequent ARG directives are for a 16-bit stack,
* far function call.
*/
@ -3688,7 +3763,7 @@ static int do_directive(Token *tline, Token **output)
StackPointer = "bp";
ArgOffset = 4;
LocalOffset = 0;
} else if (nasm_stricmp(tok_text(tline), "small") == 0) {
} else if (nasm_stricmp(arg, "small") == 0) {
/* All subsequent ARG directives are for a 16-bit stack,
* far function call. We don't support near functions.
*/
@ -3700,6 +3775,7 @@ static int do_directive(Token *tline, Token **output)
nasm_nonfatal("`%s' invalid size type", dname);
}
break;
}
case PP_ARG:
/* TASM like ARG directive to define arguments to functions, in
@ -5609,15 +5685,17 @@ static SMacro *expand_one_smacro(Token ***tpp)
switch (type) {
case TOKEN_PREPROC_Q:
case TOKEN_PREPROC_SQ:
delete_Token(t);
t = dup_Token(tline, mstart);
break;
case TOKEN_PREPROC_QQ:
case TOKEN_PREPROC_SQQ:
{
size_t mlen = strlen(m->name);
size_t len;
char *p;
char *p, *from;
t->type = mstart->type;
if (t->type == TOKEN_LOCAL_MACRO) {
@ -5630,15 +5708,15 @@ static SMacro *expand_one_smacro(Token ***tpp)
plen = pep - psp;
len = mlen + plen;
p = nasm_malloc(len + 1);
from = p = nasm_malloc(len + 1);
p = mempcpy(p, psp, plen);
} else {
len = mlen;
p = nasm_malloc(len + 1);
from = p = nasm_malloc(len + 1);
}
p = mempcpy(p, m->name, mlen);
*p = '\0';
set_text_free(t, p, len);
set_text_free(t, from, len);
t->next = tline;
break;
@ -6974,6 +7052,9 @@ static Token *pp_tokline(void)
free_tlist(m->iline);
nasm_free(m->paramlen);
fm->in_progress = 0;
m->params = NULL;
m->iline = NULL;
m->paramlen = NULL;
}
}

View File

@ -1,6 +1,7 @@
#!/usr/bin/perl
use strict;
use Fcntl qw(:seek);
use File::Find;
use File::Basename;
@ -134,8 +135,9 @@ sub sort_warnings {
my @warn_noall = @warnings;
pop @warn_noall if ($warn_noall[$#warn_noall]->{name} eq 'all');
open(my $out, '>', $outfile)
or die "$0: cannot open output file $outfile: $!\n";
my $outdata;
open(my $out, '>', \$outdata)
or die "$0: cannot create memory file: $!\n";
if ($what eq 'c') {
print $out "#include \"error.h\"\n\n";
@ -273,4 +275,21 @@ if ($what eq 'c') {
print $out "\\b \\i\\c{", $pfx, "} ", @doc, "\n";
}
}
close($out);
# Write data to file if and only if it has changed
# Windows requires append mode here
open($out, '+>>', $outfile)
or die "$0: cannot open output file $outfile: $!\n";
my $datalen = length($outdata);
my $oldlen = read($out, my $oldoutdata, $datalen+1);
if (!defined($oldlen) || $oldlen != $datalen ||
!($oldoutdata eq $outdata)) {
# Data changed, must rewrite
truncate($out, 0);
seek($out, 0, SEEK_SET)
or die "$0: cannot rewind output file $outfile: $!\n";
print $out $outdata;
}
close($out);

View File

@ -396,6 +396,18 @@ PA_ARG_ENABLED([werror],
PA_ADD_CFLAGS([-Werror=vla])]
)
dnl Warnings that are probabilistic based on the compiler version, and
dnl only should be used specifically when looking for opportunities to
dnl address or optimize these cases.
PA_ARG_ENABLED([suggestions],
[compile with compiler suggestion warnings enabled],
[PA_ADD_CFLAGS([-Wsuggest-attribute=pure])
PA_ADD_CFLAGS([-Wsuggest-attribute=const])
PA_ADD_CFLAGS([-Wsuggest-attribute=noreturn])
PA_ADD_CFLAGS([-Wsuggest-attribute=format])
PA_ADD_CFLAGS([-Wsuggest-attribute=cold])
PA_ADD_CFLAGS([-Wsuggest-attribute=malloc])])
dnl
dnl Test compiler features. On some compilers, this can be affected
dnl by -Werror options, so run this *after* those options are added.

View File

@ -7,6 +7,43 @@
The NASM 2 series supports x86-64, and is the production version of NASM
since 2007.
\S{cl-2.15.04} Version 2.15.04
\b More sensible handling of the case where one single-line macro
definition will shadow another. A warning will be issued, but the
additional definition will be allowed. For the existing error case
where both a parameterless and parametered macro are created, that
warning is promoted to an error by default.
\b Add special preprocessor tokens \c{%*?} and \c{%*??} that expand
like \c{%?} and \c{%??} in single-line macros only. See
\k{selfref%*?}.
\b Correct the encoding of the \c{ENQCMDS} and \c{TILELOADT1}
instructions.
\b Fix case where the COFF backend (the \c{coff}, \c{win32} and
\c{win64} output formats) would add padding bytes in the middle of a
section if a \c{SECTION}/\c{SEGMENT} directive was provided which
repeated an \c{ALIGN=} attribute. This neither matched legacy
behavior, other backends, or user expectations.
\b Fix SSE instructions not being recognized with an explicit memory
operation size (e.g. \c{movsd qword [eax],xmm0}).
\b The \c{-L+} option no longer enables \c{-Lw}, which is mainly
useful to debug NASM crashes. See \k{opt-L}.
\b Document long-standing hazards in the use of \c{$} in \c{Dx}
statements, see \k{db}.
\b The NASM-only RDOFF output format backend, which has been broken
since at least NASM 2.14, has been disabled. The RDOFF tools are
scheduled to be removed from the NASM distribution in NASM 2.16. If
you have a concrete use case for RDOFF, please file a NASM bug report
at \W{https://bugs.nasm.us/}\c{https://bugs.nasm.us/} as soon as
possible. See \k{rdffmt}.
\S{cl-2.15.03} Version 2.15.03
\b Add instructions from the Intel Instruction Set Extensions and

View File

@ -1,6 +1,7 @@
\# --------------------------------------------------------------------------
\#
\# Copyright 1996-2020 The NASM Authors - All Rights Reserved
\M{year}{1996-2020}
\# See the file AUTHORS included with the NASM distribution for
\# the specific copyright holders.
\#
@ -36,10 +37,9 @@
\M{category}{Programming}
\M{title}{NASM - The Netwide Assembler}
\M{year}{1996-2017}
\M{author}{The NASM Development Team}
\M{copyright_tail}{-- All Rights Reserved}
\M{license}{This document is redistributable under the license given in the file "LICENSE" distributed in the NASM archive.}
\M{license}{This document is redistributable under the license given in the section "License".}
\M{summary}{This file documents NASM, the Netwide Assembler: an assembler targetting the Intel x86 series of processors, with portable source.}
\M{infoname}{NASM}
\M{infofile}{nasm}
@ -318,17 +318,12 @@ easy to understand, similar to the syntax in the Intel Software
Developer Manual with minimal complexity. It supports all currently
known x86 architectural extensions, and has strong support for macros.
NASM also comes with a set of utilities for handling its own RDOFF2
object-file format.
\S{legal} \i{License}
\S{legal} \i{License} Conditions
NASM is under the so-called 2-clause BSD license, also
known as the simplified BSD license:
Please see the file \c{LICENSE}, supplied as part of any NASM
distribution archive, for the license conditions under which you may
use NASM. NASM is now under the so-called 2-clause BSD license, also
known as the simplified BSD license.
Copyright 1996-2017 the NASM Authors - All rights reserved.
Copyright \m{year} the NASM Authors - All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@ -493,9 +488,10 @@ Supported options are:
\b \c{-Ls} show all single-line macro definitions
\b \c{-Lw} flush the output after every line (very slow!)
\b \c{-Lw} flush the output after every line (very slow, mainly useful
to debug NASM crashes)
\b \c{-L+} enable \e{all} listing options
\b \c{-L+} enable \e{all} listing options except \c{-Lw} (very verbose)
These options can be enabled or disabled at runtime using the
\c{%pragma list options} directive:
@ -1260,12 +1256,16 @@ uninitialized}\i{uninitialized} counterparts \i\c{RESB}, \i\c{RESW},
\i\c\{RESZ}; the \i\c{INCBIN} command, the \i\c{EQU} command, and the
\i\c{TIMES} prefix.
In this documentation, the notation "\c{Dx}" and "\c{RESx}" is used to
indicate all the \c{DB} and \c{RESB} type directives, respectively.
\S{db} \c{DB} and Friends: Declaring Initialized Data
\S{db} \c{Dx}: Declaring Initialized Data
\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} are used, much as in MASM, to declare initialized data in
the output file. They can be invoked in a wide range of ways:
and \i\c{DZ} (collectively "\c{Dx}" in this documentation) are used,
much as in MASM, to declare initialized data in the output file. They
can be invoked in a wide range of ways:
\I{floating-point}\I{character constant}\I{string constant}
\c db 0x55 ; just the byte 0x55
@ -1282,8 +1282,8 @@ the output file. They can be invoked in a wide range of ways:
\c dq 1.234567e20 ; double-precision float
\c dt 1.234567e20 ; extended-precision float
\c{DT}, \c{DO}, \c{DY} and \c{DZ} do not accept \i{numeric constants}
as operands.
\c{DT}, \c{DO}, \c{DY} and \c{DZ} do not accept integer
\i{numeric constants} as operands.
\I{masmdb} Starting in NASM 2.15, a the following \i{MASM}-like features
have been implemented:
@ -1329,6 +1329,22 @@ valid:
\c dd 16 dup (0xaaaa, ?, 0xbbbbbb)
\c dd 64 dup (?)
\I{baddb} The use of \c{$} (current address) in a \c{Dx} statement is
undefined in the current version of NASM, \e{except in the following
cases}:
\b For the first expression in the statement, either a \c{DUP} or a data
item.
\b An expression of the form "\e{value}\c{ - $}", which is converted
to a self-relative relocation.
Future versions of NASM is likely to produce a different result or
issue an error this case.
There is no such restriction on using \c{$$} or section-relative
symbols.
\S{resb} \c{RESB} and Friends: Declaring \i{Uninitialized} Data
\i\c{RESB}, \i\c{RESW}, \i\c{RESD}, \i\c{RESQ}, \i\c{REST},
@ -2405,7 +2421,9 @@ macros, but for case-insensitive macros, they can differ.
For example:
\c %idefine Foo mov %?,%??
\c %imacro Foo 0
\c mov %?,%??
\c %endmacro
\c
\c foo
\c FOO
@ -2415,15 +2433,51 @@ will expand to:
\c mov foo,Foo
\c mov FOO,Foo
The sequence:
These tokens can be used for single-line macros \e{if defined outside
any multi-line macros.} See below.
\c %idefine keyword $%?
\S{selfref%*?} The Single-Line Macro Name: \i\c{%*?} and \i\c{%*??}
can be used to make a keyword "disappear", for example in case a new
instruction has been used as a label in older code. For example:
If the tokens \c{%?} and \c{%??} are used inside a multi-line macro,
they are expanded before any directives are processed. As a result,
\c %idefine pause $%? ; Hide the PAUSE instruction
\c %imacro Foo 0
\c %idefine Bar _%?
\c mov BAR,bAr
\c %endmacro
\c
\c foo
\c mov eax,bar
will expand to:
\c mov _foo,_foo
\c mov eax,_foo
which may or may not be what you expected. The tokens \c{%*?} and
\c{%*??} behave like \c{%?} and \c{%??} but are only expanded inside
single-line macros. Thus:
\c %imacro Foo 0
\c %idefine Bar _%*?
\c mov BAR,bAr
\c %endmacro
\c
\c foo
\c mov eax,bar
will expand to:
\c mov _BAR,_bAr
\c mov eax,_bar
The \c{%*?} can be used to make a keyword "disappear", for example in
case a new instruction has been used as a label in older code. For
example:
\c %idefine pause $%*? ; Hide the PAUSE instruction
\c{%*?} and \c{%*??} were introduced in NASM 2.15.04.
\S{undef} Undefining Single-Line Macros: \i\c{%undef}
@ -6662,7 +6716,14 @@ only special symbol supported is \c{..start}.
\H{rdffmt} \I{RDOFF}\i\c{rdf}: \i{Relocatable Dynamic Object File
Format}
Format} (deprecated)
\e{The RDOFF format is strongly deprecated and has been disabled
starting in NASM 2.15.04. The RDOFF backend has been broken since at
least NASM 2.14. The RDOFF utilities are scheduled to be removed from
the NASM distribution in NASM 2.16.} If you have a strong use case for
the RDOFF format, file a bug report at
\W{https://bugs.nasm.us/}\c{https://bugs.nasm.us/} as soon as possible.
The \c{rdf} output format produces \c{RDOFF} object files. \c{RDOFF}
(Relocatable Dynamic Object File Format) is a home-grown object-file
@ -6680,9 +6741,6 @@ a set of RDOFF utilities: an RDF linker, an \c{RDF} static-library
manager, an RDF file dump utility, and a program which will load and
execute an RDF executable under Linux.
\c{rdf} supports only the \i{standard section names} \i\c{.text},
\i\c{.data} and \i\c{.bss}.
\S{rdflib} Requiring a Library: The \i\c{LIBRARY} Directive

View File

@ -124,7 +124,7 @@ my $r = system($gs, "-dCompatibilityLevel${o}1.3",
$fpopt,
"-dCompressPages${o}" . ($compress ? 'true' : 'false'),
"-dUseFlateCompression${o}true",
"-c", ".setpdfwrite", "-f", $in);
"-f", $in);
exit 0 if ( !$r && -f $out );
# 3. pstopdf (BSD/MacOS X utility)

View File

@ -115,10 +115,12 @@
# another, so that \I{foobar} has the effect of \I{bazquux}, and
# \i{foobar} has the effect of \I{bazquux}foobar
#
# Metadata
# Metadata/macros
# \M{key}{something}
# defines document metadata, such as authorship, title and copyright;
# different output formats use this differently.
# \m{key}
# insert the {something} string associated with metadata {key}
#
# Include subfile
# \&{filename}
@ -270,6 +272,15 @@ sub got_para {
@$pname = ();
# Replace metadata macros
while (/^(.*)\\m\{([^\}]*)\}(.*)$/) {
if (defined($metadata{$2})) {
$_ = $1.$metadata{$2}.$3;
} else {
$_ = $1.$2.$3;
}
}
# Strip off _leading_ spaces, then determine type of paragraph.
s/^\s*//;
$irewrite = undef;
@ -660,11 +671,13 @@ sub write_txt {
}
print "$title\n";
} elsif ($ptype eq "code") {
# Code paragraph. Emit each line with a seven character indent.
foreach $i (@$pname) {
warn "code line longer than 68 chars: $i\n" if length $i > 68;
print ' 'x7, $i, "\n";
}
# Code paragraph. Emit each line with a seven character indent.
my $maxlen = 80;
foreach $i (@$pname) {
warn "code line longer than $maxlen chars: $i\n"
if ( length($i) > $maxlen );
print ' 'x7, $i, "\n";
}
} elsif ($ptype =~ /^(norm|bull|indt|bquo)$/) {
# Ordinary paragraph, optionally indented. We wrap, with ragged
# 75-char right margin and either 7 or 11 char left margin

View File

@ -326,6 +326,8 @@ static inline void *mempcpy(void *dst, const void *src, size_t n)
*/
#define printf_func(fmt, list) format_func3(printf,fmt,list)
#define printf_func_ptr(fmt, list) format_func3_ptr(printf,fmt,list)
#define vprintf_func(fmt) format_func3(printf,fmt,0)
#define vprintf_func_ptr(fmt) format_func3_ptr(printf,fmt,0)
/* Determine probabilistically if something is a compile-time constant */
#ifdef HAVE___BUILTIN_CONSTANT_P

View File

@ -72,8 +72,8 @@ fatal_func printf_func(2, 3) nasm_panicf(errflags flags, const char *fmt, ...);
fatal_func nasm_panic_from_macro(const char *file, int line);
#define panic() nasm_panic_from_macro(__FILE__, __LINE__);
void nasm_verror(errflags severity, const char *fmt, va_list ap);
fatal_func nasm_verror_critical(errflags severity, const char *fmt, va_list ap);
void vprintf_func(2) nasm_verror(errflags severity, const char *fmt, va_list ap);
fatal_func vprintf_func(2) nasm_verror_critical(errflags severity, const char *fmt, va_list ap);
/*
* These are the error severity codes which get passed as the first

View File

@ -250,6 +250,8 @@ enum token_type { /* token types, other than chars */
TOKEN_NAKED_STR, /* Unquoted string that can be re-quoted */
TOKEN_PREPROC_Q, /* %? */
TOKEN_PREPROC_QQ, /* %?? */
TOKEN_PREPROC_SQ, /* %*? */
TOKEN_PREPROC_SQQ, /* %*? */
TOKEN_PASTE, /* %+ */
TOKEN_COND_COMMA, /* %, */
TOKEN_INDIRECT, /* %[...] */
@ -617,13 +619,14 @@ enum prefixes { /* instruction prefixes */
};
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 */
EAF_TIMESTWO = 4, /* really do EAX*2 not EAX+EAX */
EAF_REL = 8, /* IP-relative addressing */
EAF_ABS = 16, /* non-IP-relative addressing */
EAF_FSGS = 32, /* fs/gs segment override present */
EAF_MIB = 64 /* mib operand */
EAF_BYTEOFFS = 1, /* force offset part to byte size */
EAF_WORDOFFS = 2, /* force offset part to [d]word size */
EAF_TIMESTWO = 4, /* really do EAX*2 not EAX+EAX */
EAF_REL = 8, /* IP-relative addressing */
EAF_ABS = 16, /* non-IP-relative addressing */
EAF_FSGS = 32, /* fs/gs segment override present */
EAF_MIB = 64, /* mib operand */
EAF_SIB = 128 /* SIB encoding obligatory */
};
enum eval_hint { /* values for `hinttype' */

View File

@ -83,9 +83,9 @@ char * safe_alloc end_with_null nasm_strcatn(const char *one, ...);
* this additional storage.
*/
char * safe_alloc printf_func(1, 2) nasm_asprintf(const char *fmt, ...);
char * safe_alloc nasm_vasprintf(const char *fmt, va_list ap);
char * safe_alloc vprintf_func(1) nasm_vasprintf(const char *fmt, va_list ap);
void * safe_alloc printf_func(2, 3) nasm_axprintf(size_t extra, const char *fmt, ...);
void * safe_alloc nasm_vaxprintf(size_t extra, const char *fmt, va_list ap);
void * safe_alloc vprintf_func(2) nasm_vaxprintf(size_t extra, const char *fmt, va_list ap);
/*
* nasm_last_string_len() returns the length of the last string allocated

View File

@ -81,7 +81,7 @@ 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 *
const struct strlist_entry * vprintf_func(2)
strlist_vprintf(struct strlist *list, const char *fmt, va_list ap);
const struct strlist_entry *
strlist_find(const struct strlist *list, const char *str);

View File

@ -308,7 +308,7 @@ static void build_type_table(struct coff_Section *const sect);
static void cv8_cleanup(void)
{
struct cv8_symbol *sym;
struct source_file *file;
struct source_file *file, *ftmp;
struct coff_Section *symbol_sect = coff_sects[cv8_state.symbol_sect];
struct coff_Section *type_sect = coff_sects[cv8_state.type_sect];
@ -319,10 +319,10 @@ static void cv8_cleanup(void)
build_symbol_table(symbol_sect);
build_type_table(type_sect);
list_for_each(file, cv8_state.source_files) {
list_for_each_safe(file, ftmp, cv8_state.source_files) {
nasm_free(file->fullname);
saa_free(file->lines);
free(file);
nasm_free(file);
}
hash_free(&cv8_state.file_hash);
@ -401,8 +401,7 @@ static struct source_file *register_file(const char *filename)
fullpath = nasm_realpath(filename);
file = nasm_zalloc(sizeof(*file));
nasm_new(file);
file->filename = filename;
file->fullname = fullpath;
file->fullnamelen = strlen(fullpath);

View File

@ -420,36 +420,12 @@ static int32_t coff_section_names(char *name, int *bits)
}
}
/* Check if alignment might be needed */
if (align_flags) {
uint32_t sect_align_flags = coff_sects[i]->align_flags;
/* Compute the actual alignment */
unsigned int align = coff_alignment(align_flags);
/* Update section header as needed */
if (align_flags > sect_align_flags) {
coff_sects[i]->align_flags = align_flags;
}
/* Check if not already aligned */
/* XXX: other formats don't do this... */
if (coff_sects[i]->len % align) {
unsigned int padding = (align - coff_sects[i]->len) % align;
/* We need to write at most 8095 bytes */
char buffer[8095];
nasm_assert(padding <= sizeof buffer);
if (coff_sects[i]->flags & IMAGE_SCN_CNT_CODE) {
/* Fill with INT 3 instructions */
memset(buffer, 0xCC, padding);
} else {
memset(buffer, 0x00, padding);
}
saa_wbytes(coff_sects[i]->data, buffer, padding);
coff_sects[i]->len += padding;
}
/*
* Alignment can be increased, but never decreased. However,
* specifying a narrower alignment is permitted and ignored.
*/
if (align_flags > coff_sects[i]->align_flags) {
coff_sects[i]->align_flags = align_flags;
}
}

View File

@ -130,9 +130,6 @@
#ifndef OF_AS86
#define OF_AS86
#endif
#ifndef OF_RDF2
#define OF_RDF2
#endif
#ifndef OF_IEEE
#define OF_IEEE
#endif
@ -194,9 +191,6 @@
#ifndef OF_AS86
#define OF_AS86
#endif
#ifndef OF_RDF2
#define OF_RDF2
#endif
#ifndef OF_IEEE
#define OF_IEEE
#endif

View File

@ -1128,15 +1128,15 @@ static void ieee_write_dword(struct ieeeSection *seg, int32_t data)
ieee_write_byte(seg, (data >> 16) & 0xFF);
ieee_write_byte(seg, (data >> 24) & 0xFF);
}
static void ieee_putascii(char *format, ...)
static void printf_func(1, 2) ieee_putascii(char *format, ...)
{
char buffer[256];
int i, l;
size_t i, l;
va_list ap;
va_start(ap, format);
vsnprintf(buffer, sizeof(buffer), format, ap);
l = strlen(buffer);
l = vsnprintf(buffer, sizeof(buffer), format, ap);
nasm_assert(l < sizeof(buffer));
for (i = 0; i < l; i++)
if ((uint8_t)buffer[i] > 31)
checksum += buffer[i];

View File

@ -424,6 +424,12 @@ static ObjRecord *obj_name(ObjRecord * orp, const char *name)
int len = strlen(name);
uint8_t *ptr;
if (len > UINT8_MAX) {
nasm_warn(WARN_OTHER, "truncating object name `%.64s...' to %u bytes",
name, UINT8_MAX);
len = UINT8_MAX;
}
orp = obj_check(orp, len + 1);
ptr = orp->buf + orp->used;
*ptr++ = len;

21
test/br3392707.asm Normal file
View File

@ -0,0 +1,21 @@
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 (?,?)
dw byte (?,44)
dw 0xcc, 4 dup byte ('PQR'), ?, 0xabcd
dd 16 dup (0xaaaa, ?, 0xbbbbbb)
dd 64 dup (?)

BIN
test/br3392708.asm Normal file

Binary file not shown.

17
test/coffalign.asm Normal file
View File

@ -0,0 +1,17 @@
section .text align=64
foo:
nop
nop
nop
ret
section .data align=64
bar:
db 0, 1, 2
section .text align=32
baz:
nop
nop
nop
ret

36
test/immsize.asm Normal file
View File

@ -0,0 +1,36 @@
bits 64
%macro b 1
%1 ax,16
%1 eax,16
%1 rax,16
%1 word [rdi],16
%1 dword [rdi],16
%1 qword [rdi],16
%1 ax,byte 16
%1 eax,byte 16
%1 rax,byte 16
%1 word [rdi],byte 16
%1 dword [rdi],byte 16
%1 qword [rdi],byte 16
%endmacro
b bt
b btc
b btr
b bts
imul ax,[rdi],16
imul ax,word [rdi],16
imul ax,[rdi],byte 16
imul ax,word [rdi],byte 16
imul eax,[rdi],16
imul eax,dword [rdi],16
imul eax,[rdi],byte 16
imul eax,dword [rdi],byte 16
imul rax,[rdi],16
imul rax,qword [rdi],16
imul rax,[rdi],byte 16
imul rax,qword [rdi],byte 16

10
test/insertps.asm Normal file
View File

@ -0,0 +1,10 @@
bits 64
insertps xmm0,xmm1,16
insertps xmm0,dword xmm1,16
insertps xmm0,xmm1,byte 16
insertps xmm0,dword xmm1,byte 16
insertps xmm0,[rax],16
insertps xmm0,dword [rax],16
insertps xmm0,[rax],byte 16
insertps xmm0,dword [rax],byte 16

15
test/movhpd.asm Normal file
View File

@ -0,0 +1,15 @@
bits 64
movhpd xmm0,[rdi+2]
movhpd xmm0,qword [rdi+2]
movhpd [rsi+3],xmm1
movhpd qword [rsi+3],xmm1
vmovhpd xmm2,xmm1,[rax+4]
vmovhpd xmm2,xmm1,qword [rax+4]
vmovhpd xmm3,[rax+4]
vmovhpd xmm3,qword [rax+4]
vmovhpd [rcx+5],xmm4
vmovhpd qword [rcx+5],xmm4

24
test/selfref.asm Normal file
View File

@ -0,0 +1,24 @@
bits 32
%idefine zoom $%?
mov ebx,Zoom
%idefine boom $%?
mov ecx,Boom
%imacro Foo1 0
%idefine Bar1 _%?
%idefine baz1 $%?
mov BAR1,baz1
%endmacro
foo1
mov eax,bar1
%imacro Foo2 0
%idefine Bar2 _%*?
%idefine baz2 $%*?
mov BAR2,baz2
%endmacro
foo2
mov eax,bar2

14
test/ssesize.asm Normal file
View File

@ -0,0 +1,14 @@
_start:
movd ecx,xmm0
movd [foo],xmm0
movd dword [foo],xmm0
movdqa xmm1,xmm0
movdqa [foo],xmm0
movdqa oword [foo],xmm0
cmppd xmm2,xmm3,8
cmppd xmm2,xmm3,byte 8
section .bss
foo: reso 1

27
test/vpcmp.asm Normal file
View File

@ -0,0 +1,27 @@
bits 64
vpcmpeqb k2{k2},zmm0,zmm1
vpcmpgtb k2{k2},zmm0,zmm1
vpcmpeqw k2{k2},zmm0,zmm1
vpcmpgtw k2{k2},zmm0,zmm1
vpcmpeqd k2{k2},zmm0,zmm1
vpcmpgtd k2{k2},zmm0,zmm1
vpcmpeqq k2{k2},zmm0,zmm1
vpcmpgtq k2{k2},zmm0,zmm1
vpcmpb k2{k2},zmm0,zmm1,0
vpcmpb k2{k2},zmm0,zmm1,6
vpcmpw k2{k2},zmm0,zmm1,0
vpcmpw k2{k2},zmm0,zmm1,6
vpcmpd k2{k2},zmm0,zmm1,0
vpcmpd k2{k2},zmm0,zmm1,6
vpcmpq k2{k2},zmm0,zmm1,0
vpcmpq k2{k2},zmm0,zmm1,6
vpcmpneqb k2{k2},zmm0,zmm1
vpcmpleb k2{k2},zmm0,zmm1
vpcmpneqw k2{k2},zmm0,zmm1
vpcmplew k2{k2},zmm0,zmm1
vpcmpneqd k2{k2},zmm0,zmm1
vpcmpled k2{k2},zmm0,zmm1
vpcmpneqq k2{k2},zmm0,zmm1
vpcmpleq k2{k2},zmm0,zmm1

View File

@ -0,0 +1,4 @@
;
; Test long section name to be trimmed down to RECORD_MAX
;
section .name0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789

View File

@ -0,0 +1,13 @@
[
{
"description": "Test br3392643 (name limit in OBJ files)",
"id": "br3392643",
"format": "obj",
"source": "br3392643.asm",
"option": "-Ox",
"target": [
{ "output": "br3392643.obj" },
{ "stderr": "br3392643.stderr" }
]
}
]

BIN
travis/test/br3392643.obj.t Normal file

Binary file not shown.

View File

@ -0,0 +1 @@
./travis/test/br3392643.asm: warning: truncating object name `name012345678901234567890123456789012345678901234567890123456789...' to 255 bytes [-w+other]

18
travis/test/br3392711.asm Normal file
View File

@ -0,0 +1,18 @@
;
; In br33927711 we've not been expanding %?? and %*?? correctly
;
section .text
%define label(prefix, suffix) prefix %+ suffix
label_1:
mov eax, label(%??, _1)
label_2:
mov eax, label(%?, _2)
%define label0123456789a0123456789a0123456789a0123456789a0123456789a0123456789a0123456789(prefix, suffix) prefix %+ suffix
label0123456789a0123456789a0123456789a0123456789a0123456789a0123456789a0123456789_1:
mov eax, label0123456789a0123456789a0123456789a0123456789a0123456789a0123456789a0123456789(%??, _1)
label0123456789a0123456789a0123456789a0123456789a0123456789a0123456789a0123456789_2:
mov eax, label0123456789a0123456789a0123456789a0123456789a0123456789a0123456789a0123456789(%??, _2)

View File

@ -0,0 +1,12 @@
[
{
"description": "Test br3392711 (%?? and %? expansion)",
"id": "br3392711",
"format": "elf64",
"source": "br3392711.asm",
"option": "-Ox",
"target": [
{ "output": "br3392711.o" }
]
}
]

BIN
travis/test/br3392711.o.t Normal file

Binary file not shown.

View File

@ -36,7 +36,8 @@ if_("LOCK", "Lockable if operand 0 is memory");
if_("NOLONG", "Not available in long mode");
if_("LONG", "Long mode");
if_("NOHLE", "HLE prefixes forbidden");
if_("MIB", "disassemble with split EA");
if_("MIB", "split base/index EA");
if_("SIB", "SIB encoding required");
if_("BND", "BND (0xF2) prefix available");
if_("UNDOC", "Undocumented");
if_("HLE", "HLE prefixed");

File diff suppressed because it is too large Load Diff

View File

@ -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.
##
@ -444,7 +444,7 @@ sub format_insn($$$$$) {
my $nd = 0;
my ($num, $flagsindex);
my @bytecode;
my ($op, @ops, $opp, @opx, @oppx, @decos, @opevex);
my ($op, @ops, @opsize, $opp, @opx, @oppx, @decos, @opevex);
return (undef, undef) if $operands eq "ignore";
@ -452,9 +452,11 @@ sub format_insn($$$$$) {
$operands =~ s/\*//g;
$operands =~ s/:/|colon,/g;
@ops = ();
@opsize = ();
@decos = ();
if ($operands ne 'void') {
foreach $op (split(/,/, $operands)) {
my $opsz = 0;
@opx = ();
@opevex = ();
foreach $opp (split(/\|/, $op)) {
@ -465,6 +467,7 @@ sub format_insn($$$$$) {
if ($opp =~ s/(?<!\d)(8|16|32|64|80|128|256|512)$//) {
push(@oppx, "bits$1");
$opsz = $1 + 0;
}
$opp =~ s/^mem$/memory/;
$opp =~ s/^memory_offs$/mem_offs/;
@ -481,6 +484,7 @@ sub format_insn($$$$$) {
}
$op = join('|', @opx);
push(@ops, $op);
push(@opsize, $opsz);
push(@decos, (@opevex ? join('|', @opevex) : '0'));
}
}
@ -488,6 +492,7 @@ sub format_insn($$$$$) {
$num = scalar(@ops);
while (scalar(@ops) < $MAX_OPERANDS) {
push(@ops, '0');
push(@opsize, 0);
push(@decos, '0');
}
$operands = join(',', @ops);
@ -499,16 +504,17 @@ sub format_insn($$$$$) {
}
$decorators =~ tr/a-z/A-Z/;
# Remember if we have an ARx flag
my $arx = undef;
# expand and uniqify the flags
my %flags;
foreach my $flag (split(',', $flags)) {
next if ($flag eq '');
if ($flag eq 'ND') {
$nd = 1;
} elsif ($flag eq 'X64') {
# X64 is shorthand for "LONG,X86_64"
$flags{'LONG'}++;
$flags{'X86_64'}++;
} elsif ($flag ne '') {
} else {
$flags{$flag}++;
}
@ -516,6 +522,10 @@ sub format_insn($$$$$) {
# These flags imply OBSOLETE
$flags{'OBSOLETE'}++;
}
if ($flag =~ /^AR([0-9]+)$/) {
$arx = $1+0;
}
}
if ($codes =~ /evex\./) {
@ -524,8 +534,41 @@ sub format_insn($$$$$) {
$flags{'VEX'}++;
}
# Look for SM flags clearly inconsistent with operand bitsizes
if ($flags{'SM'} || $flags{'SM2'}) {
my $ssize = 0;
my $e = $flags{'SM2'} ? 2 : $MAX_OPERANDS;
for (my $i = 0; $i < $e; $i++) {
next if (!$opsize[$i]);
if (!$ssize) {
$ssize = $opsize[$i];
} elsif ($opsize[$i] != $ssize) {
die "$fname:$line: inconsistent SM flag for argument $i\n";
}
}
}
# Look for Sx flags that can never match operand bitsizes. If the
# intent is to never match (require explicit sizes), use the SX flag.
# This doesn't apply to registers that pre-define specific sizes;
# this should really be derived from include/opflags.h...
my %sflags = ( 'SB' => 8, 'SW' => 16, 'SD' => 32, 'SQ' => 64,
'SO' => 128, 'SY' => 256, 'SZ' => 512 );
my $s = defined($arx) ? $arx : 0;
my $e = defined($arx) ? $arx : $MAX_OPERANDS - 1;
foreach my $sf (keys(%sflags)) {
next if (!$flags{$sf});
for (my $i = $s; $i <= $e; $i++) {
if ($opsize[$i] && $ops[$i] !~ /\breg_(gpr|[cdts]reg)\b/) {
die "$fname:$line: inconsistent $sf flag for argument $i ($ops[$i])\n"
if ($opsize[$i] != $sflags{$sf});
}
}
}
$flagsindex = insns_flag_index(keys %flags);
die "$fname:$line: error in flags $flags" unless (defined($flagsindex));
die "$fname:$line: error in flags $flags\n" unless (defined($flagsindex));
@bytecode = (decodify($codes, $relax), 0);
push(@bytecode_list, [@bytecode]);