mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-04-06 18:30:21 +08:00
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:
commit
cc843efa38
29
Makefile.in
29
Makefile.in
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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--;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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"
|
||||
|
16
asm/parser.c
16
asm/parser.c
@ -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;
|
||||
}
|
||||
|
179
asm/preproc.c
179
asm/preproc.c
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
12
configure.ac
12
configure.ac
@ -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.
|
||||
|
@ -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
|
||||
|
114
doc/nasmdoc.src
114
doc/nasmdoc.src
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
25
doc/rdsrc.pl
25
doc/rdsrc.pl
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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' */
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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
21
test/br3392707.asm
Normal 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
BIN
test/br3392708.asm
Normal file
Binary file not shown.
17
test/coffalign.asm
Normal file
17
test/coffalign.asm
Normal 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
36
test/immsize.asm
Normal 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
10
test/insertps.asm
Normal 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
15
test/movhpd.asm
Normal 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
24
test/selfref.asm
Normal 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
14
test/ssesize.asm
Normal 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
27
test/vpcmp.asm
Normal 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
|
4
travis/test/br3392643.asm
Normal file
4
travis/test/br3392643.asm
Normal file
@ -0,0 +1,4 @@
|
||||
;
|
||||
; Test long section name to be trimmed down to RECORD_MAX
|
||||
;
|
||||
section .name0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
13
travis/test/br3392643.json
Normal file
13
travis/test/br3392643.json
Normal 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
BIN
travis/test/br3392643.obj.t
Normal file
Binary file not shown.
1
travis/test/br3392643.stderr
Normal file
1
travis/test/br3392643.stderr
Normal 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
18
travis/test/br3392711.asm
Normal 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)
|
12
travis/test/br3392711.json
Normal file
12
travis/test/br3392711.json
Normal 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
BIN
travis/test/br3392711.o.t
Normal file
Binary file not shown.
@ -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");
|
||||
|
1087
x86/insns.dat
1087
x86/insns.dat
File diff suppressed because it is too large
Load Diff
59
x86/insns.pl
59
x86/insns.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.
|
||||
##
|
||||
@ -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]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user