mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-07-24 10:25:42 -04: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
|
FIND = find
|
||||||
|
|
||||||
# Binary suffixes
|
# Binary suffixes
|
||||||
O = @OBJEXT@
|
O = @OBJEXT@
|
||||||
X = @EXEEXT@
|
X = @EXEEXT@
|
||||||
A = @LIBEXT@
|
A = @LIBEXT@
|
||||||
|
|
||||||
# Debug stuff
|
# Debug stuff
|
||||||
@ -97,7 +97,7 @@ endif
|
|||||||
$(XMLTO) man --skip-validation $< 2>/dev/null
|
$(XMLTO) man --skip-validation $< 2>/dev/null
|
||||||
|
|
||||||
#-- Begin File Lists --#
|
#-- Begin File Lists --#
|
||||||
NASM = asm/nasm.$(O)
|
NASM = asm/nasm.$(O)
|
||||||
NDISASM = disasm/ndisasm.$(O)
|
NDISASM = disasm/ndisasm.$(O)
|
||||||
|
|
||||||
LIBOBJ = stdlib/snprintf.$(O) stdlib/vsnprintf.$(O) stdlib/strlcpy.$(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)
|
disasm/disasm.$(O) disasm/sync.$(O)
|
||||||
|
|
||||||
|
ALLOBJ = $(NASM) $(NDISASM) $(LIBOBJ)
|
||||||
|
|
||||||
SUBDIRS = stdlib nasmlib output asm disasm x86 common macros
|
SUBDIRS = stdlib nasmlib output asm disasm x86 common macros
|
||||||
XSUBDIRS = test doc nsis rdoff
|
XSUBDIRS = test doc nsis rdoff
|
||||||
DEPDIRS = . include config x86 rdoff $(SUBDIRS)
|
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 \
|
$(RUNPERL) $(srcdir)/x86/regs.pl h \
|
||||||
$(srcdir)/x86/regs.dat > x86/regs.h
|
$(srcdir)/x86/regs.dat > x86/regs.h
|
||||||
|
|
||||||
# Extract warnings from source code. Since this depends on
|
# Extract warnings from source code. This is done automatically if any
|
||||||
# ALL the source files, this is only done on demand.
|
# 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
|
WARNFILES = asm/warnings.c include/warnings.h doc/warnings.src
|
||||||
|
|
||||||
warnings:
|
warnings:
|
||||||
$(RM_F) $(WARNFILES)
|
$(RM_F) $(WARNFILES)
|
||||||
|
$(MAKE) asm/warnings.time
|
||||||
|
|
||||||
|
asm/warnings.time: $(ALLOBJ:.@OBJEXT@=.c)
|
||||||
|
: > asm/warnings.time
|
||||||
$(MAKE) $(WARNFILES)
|
$(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)
|
$(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)
|
$(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)
|
$(RUNPERL) $(srcdir)/asm/warnings.pl doc doc/warnings.src $(srcdir)
|
||||||
|
|
||||||
# Assembler token hash
|
# Assembler token hash
|
||||||
@ -402,12 +411,12 @@ distclean: clean
|
|||||||
done
|
done
|
||||||
$(RM_F) test/*.$(O)
|
$(RM_F) test/*.$(O)
|
||||||
$(RM_RF) autom4te*.cache
|
$(RM_RF) autom4te*.cache
|
||||||
$(RM_F) Makefile *.dep
|
$(RM_F) Makefile *.dep asm/warnings.time
|
||||||
|
|
||||||
cleaner: clean
|
cleaner: clean
|
||||||
$(RM_F) $(PERLREQ) *.1 nasm.spec
|
$(RM_F) $(PERLREQ) *.1 nasm.spec
|
||||||
$(MAKE) -C doc clean
|
$(MAKE) -C doc clean
|
||||||
$(RM_F) *.dep
|
$(RM_F) *.dep asm/warnings.time
|
||||||
|
|
||||||
spotless: distclean cleaner
|
spotless: distclean cleaner
|
||||||
$(RM_F) doc/Makefile
|
$(RM_F) doc/Makefile
|
||||||
|
@ -61,7 +61,7 @@ X = .exe
|
|||||||
|
|
||||||
#-- Begin File Lists --#
|
#-- Begin File Lists --#
|
||||||
# Edit in Makefile.in, not here!
|
# Edit in Makefile.in, not here!
|
||||||
NASM = asm\nasm.$(O)
|
NASM = asm\nasm.$(O)
|
||||||
NDISASM = disasm\ndisasm.$(O)
|
NDISASM = disasm\ndisasm.$(O)
|
||||||
|
|
||||||
LIBOBJ = stdlib\snprintf.$(O) stdlib\vsnprintf.$(O) stdlib\strlcpy.$(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)
|
disasm\disasm.$(O) disasm\sync.$(O)
|
||||||
|
|
||||||
|
ALLOBJ = $(NASM) $(NDISASM) $(LIBOBJ)
|
||||||
|
|
||||||
SUBDIRS = stdlib nasmlib output asm disasm x86 common macros
|
SUBDIRS = stdlib nasmlib output asm disasm x86 common macros
|
||||||
XSUBDIRS = test doc nsis rdoff
|
XSUBDIRS = test doc nsis rdoff
|
||||||
DEPDIRS = . include config x86 rdoff $(SUBDIRS)
|
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 \
|
$(RUNPERL) $(srcdir)\x86\regs.pl h \
|
||||||
$(srcdir)\x86\regs.dat > x86\regs.h
|
$(srcdir)\x86\regs.dat > x86\regs.h
|
||||||
|
|
||||||
# Extract warnings from source code. Since this depends on
|
# Extract warnings from source code. This is done automatically if any
|
||||||
# ALL the source files, this is only done on demand.
|
# 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
|
WARNFILES = asm\warnings.c include\warnings.h doc\warnings.src
|
||||||
|
|
||||||
warnings:
|
warnings:
|
||||||
$(RM_F) $(WARNFILES)
|
$(RM_F) $(WARNFILES)
|
||||||
|
$(MAKE) asm\warnings.time
|
||||||
|
|
||||||
|
asm\warnings.time: $(ALLOBJ:.@OBJEXT@=.c)
|
||||||
|
: > asm\warnings.time
|
||||||
$(MAKE) $(WARNFILES)
|
$(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)
|
$(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)
|
$(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)
|
$(RUNPERL) $(srcdir)\asm\warnings.pl doc doc\warnings.src $(srcdir)
|
||||||
|
|
||||||
# Assembler token hash
|
# Assembler token hash
|
||||||
|
@ -50,7 +50,7 @@ X = .exe
|
|||||||
|
|
||||||
#-- Begin File Lists --#
|
#-- Begin File Lists --#
|
||||||
# Edit in Makefile.in, not here!
|
# Edit in Makefile.in, not here!
|
||||||
NASM = asm\nasm.$(O)
|
NASM = asm\nasm.$(O)
|
||||||
NDISASM = disasm\ndisasm.$(O)
|
NDISASM = disasm\ndisasm.$(O)
|
||||||
|
|
||||||
LIBOBJ = stdlib\snprintf.$(O) stdlib\vsnprintf.$(O) stdlib\strlcpy.$(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)
|
disasm\disasm.$(O) disasm\sync.$(O)
|
||||||
|
|
||||||
|
ALLOBJ = $(NASM) $(NDISASM) $(LIBOBJ)
|
||||||
|
|
||||||
SUBDIRS = stdlib nasmlib output asm disasm x86 common macros
|
SUBDIRS = stdlib nasmlib output asm disasm x86 common macros
|
||||||
XSUBDIRS = test doc nsis rdoff
|
XSUBDIRS = test doc nsis rdoff
|
||||||
DEPDIRS = . include config x86 rdoff $(SUBDIRS)
|
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 &
|
$(RUNPERL) $(srcdir)\x86\regs.pl h &
|
||||||
$(srcdir)\x86\regs.dat > x86\regs.h
|
$(srcdir)\x86\regs.dat > x86\regs.h
|
||||||
|
|
||||||
# Extract warnings from source code. Since this depends on
|
# Extract warnings from source code. This is done automatically if any
|
||||||
# ALL the source files, this is only done on demand.
|
# 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
|
WARNFILES = asm\warnings.c include\warnings.h doc\warnings.src
|
||||||
|
|
||||||
warnings:
|
warnings:
|
||||||
$(RM_F) $(WARNFILES)
|
$(RM_F) $(WARNFILES)
|
||||||
|
$(MAKE) asm\warnings.time
|
||||||
|
|
||||||
|
asm\warnings.time: $(ALLOBJ:.@OBJEXT@=.c)
|
||||||
|
: > asm\warnings.time
|
||||||
$(MAKE) $(WARNFILES)
|
$(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)
|
$(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)
|
$(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)
|
$(RUNPERL) $(srcdir)\asm\warnings.pl doc doc\warnings.src $(srcdir)
|
||||||
|
|
||||||
# Assembler token hash
|
# Assembler token hash
|
||||||
|
@ -1246,7 +1246,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
|
|||||||
enum ea_type eat;
|
enum ea_type eat;
|
||||||
uint8_t hleok = 0;
|
uint8_t hleok = 0;
|
||||||
bool lockcheck = true;
|
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;
|
const char *errmsg;
|
||||||
|
|
||||||
ins->rex = 0; /* Ensure REX is reset */
|
ins->rex = 0; /* Ensure REX is reset */
|
||||||
@ -1282,7 +1282,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case4(014):
|
case4(014):
|
||||||
/* this is an index reg of MIB operand */
|
/* this is an index reg of a split SIB operand */
|
||||||
mib_index = opx->basereg;
|
mib_index = opx->basereg;
|
||||||
break;
|
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,
|
if (process_ea(opy, &ea_data, bits,
|
||||||
rfield, rflags, ins, &errmsg) != eat) {
|
rfield, rflags, ins, &errmsg) != eat) {
|
||||||
nasm_nonfatal("%s", errmsg);
|
nasm_nonfatal("%s", errmsg);
|
||||||
@ -2833,9 +2837,8 @@ static enum ea_type process_ea(operand *input, ea *output, int bits,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bits == 64 &&
|
if (bits == 64 && !(IP_REL & ~input->type) && (eaflags & EAF_SIB)) {
|
||||||
!(IP_REL & ~input->type) && (eaflags & EAF_MIB)) {
|
*errmsg = "instruction requires SIB encoding, cannot be RIP-relative";
|
||||||
*errmsg = "RIP-relative addressing is prohibited for MIB";
|
|
||||||
goto err;
|
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)))
|
input->disp_size != (addrbits != 16 ? 32 : 16)))
|
||||||
nasm_warn(WARN_OTHER, "displacement size ignored on absolute address");
|
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_present = true;
|
||||||
output->sib = GEN_SIB(0, 4, 5);
|
output->sib = GEN_SIB(0, 4, 5);
|
||||||
output->bytes = 4;
|
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;
|
bt = it, bx = ix, it = -1, ix = 0;
|
||||||
}
|
}
|
||||||
if (eaflags & EAF_MIB) {
|
if (eaflags & EAF_MIB) {
|
||||||
/* only for mib operands */
|
/* MIB/split-SIB encoding */
|
||||||
if (it == -1 && (hb == b && ht == EAH_NOTBASE)) {
|
if (it == -1 && (hb == b && ht == EAH_NOTBASE)) {
|
||||||
/*
|
/*
|
||||||
* make a single reg index [reg*1].
|
* 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(it, ix, REX_X);
|
||||||
output->rex |= rexflags(bt, bx, REX_B);
|
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 */
|
/* no SIB needed */
|
||||||
int mod, rm;
|
int mod, rm;
|
||||||
|
|
||||||
|
@ -727,7 +727,7 @@ static expr *eval_floatize(enum floatize type)
|
|||||||
len = fmt->bytes - fmt->offset;
|
len = fmt->bytes - fmt->offset;
|
||||||
if (len > 8)
|
if (len > 8)
|
||||||
len = 8; /* Max 64 bits */
|
len = 8; /* Max 64 bits */
|
||||||
p = result + len;
|
p = result + len + fmt->offset;
|
||||||
val = 0;
|
val = 0;
|
||||||
for (i = len; i; i--) {
|
for (i = len; i; i--) {
|
||||||
p--;
|
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;
|
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
|
* See the file AUTHORS included with the NASM distribution for
|
||||||
* the specific copyright holders.
|
* 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
|
* computation is needed is when parsing the -L option or %pragma list
|
||||||
* options, neither of which is in any way performance critical.
|
* 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 >= 'a') {
|
||||||
if (x > 'z')
|
if (x > 'z')
|
||||||
@ -156,8 +157,6 @@ static inline const_func uint64_t list_option_mask(unsigned char x)
|
|||||||
if (x > '9')
|
if (x > '9')
|
||||||
return 0;
|
return 0;
|
||||||
x = x - '0' + 2 + 26*2;
|
x = x - '0' + 2 + 26*2;
|
||||||
} else if (x == '+') {
|
|
||||||
return ~UINT64_C(1);
|
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -165,6 +164,14 @@ static inline const_func uint64_t list_option_mask(unsigned char x)
|
|||||||
return UINT64_C(1) << 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. */
|
/* Return true if the listing engine is active and a certain option is set. */
|
||||||
static inline pure_func bool list_option(unsigned char x)
|
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"
|
" -Lm show multi-line macro calls with expanded parmeters\n"
|
||||||
" -Lp output a list file every pass, in case of errors\n"
|
" -Lp output a list file every pass, in case of errors\n"
|
||||||
" -Ls show all single-line macro definitions\n"
|
" -Ls show all single-line macro definitions\n"
|
||||||
" -Lw flush the output after every line\n"
|
" -Lw flush the output after every line (very slow!)\n"
|
||||||
" -L+ enable all listing options (very verbose!)\n"
|
" -L+ enable all listing options except -Lw (very verbose!)\n"
|
||||||
"\n"
|
"\n"
|
||||||
" -Oflags... optimize opcodes, immediates and branch offsets\n"
|
" -Oflags... optimize opcodes, immediates and branch offsets\n"
|
||||||
" -O0 no optimization\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 */
|
/* Subexpression is empty */
|
||||||
eop->type = EOT_NOTHING;
|
eop->type = EOT_NOTHING;
|
||||||
} else if (!subexpr->next) {
|
} else if (!subexpr->next) {
|
||||||
/* Subexpression is a single element, flatten */
|
/*
|
||||||
eop->val = subexpr->val;
|
* Subexpression is a single element, flatten.
|
||||||
eop->type = subexpr->type;
|
* Note that if subexpr has an allocated buffer associated
|
||||||
eop->dup *= subexpr->dup;
|
* with it, freeing it would free the buffer, too, so
|
||||||
nasm_free(subexpr);
|
* 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 {
|
} else {
|
||||||
eop->type = EOT_EXTOP;
|
eop->type = EOT_EXTOP;
|
||||||
}
|
}
|
||||||
|
179
asm/preproc.c
179
asm/preproc.c
@ -1347,6 +1347,11 @@ static Token *tokenize(const char *line)
|
|||||||
p++;
|
p++;
|
||||||
if (*p == '?')
|
if (*p == '?')
|
||||||
p++;
|
p++;
|
||||||
|
} else if (*p == '*' && p[1] == '?') {
|
||||||
|
/* %*? and %*?? */
|
||||||
|
p += 2;
|
||||||
|
if (*p == '?')
|
||||||
|
p++;
|
||||||
} else if (*p == '!') {
|
} else if (*p == '!') {
|
||||||
/* Environment variable reference */
|
/* Environment variable reference */
|
||||||
p++;
|
p++;
|
||||||
@ -1407,6 +1412,16 @@ static Token *tokenize(const char *line)
|
|||||||
type = TOKEN_PREPROC_ID;
|
type = TOKEN_PREPROC_ID;
|
||||||
break;
|
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 '!':
|
case '!':
|
||||||
type = (toklen == 2) ? TOKEN_OTHER : TOKEN_ENVIRON;
|
type = (toklen == 2) ? TOKEN_OTHER : TOKEN_ENVIRON;
|
||||||
break;
|
break;
|
||||||
@ -2335,9 +2350,8 @@ restart:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (defn) {
|
if (defn)
|
||||||
*defn = (nparam == m->nparam || nparam == -1) ? m : NULL;
|
*defn = m;
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
m = m->next;
|
m = m->next;
|
||||||
@ -2986,7 +3000,8 @@ static SMacro *define_smacro(const char *mname, bool casesense,
|
|||||||
struct hash_table *smtbl;
|
struct hash_table *smtbl;
|
||||||
Context *ctx;
|
Context *ctx;
|
||||||
bool defining_alias = false;
|
bool defining_alias = false;
|
||||||
unsigned int nparam = 0;
|
int nparam = 0;
|
||||||
|
bool defined;
|
||||||
|
|
||||||
if (tmpl) {
|
if (tmpl) {
|
||||||
defining_alias = tmpl->alias;
|
defining_alias = tmpl->alias;
|
||||||
@ -2995,46 +3010,99 @@ static SMacro *define_smacro(const char *mname, bool casesense,
|
|||||||
mark_smac_params(expansion, tmpl, 0);
|
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)) {
|
defined = 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;
|
|
||||||
|
|
||||||
smac->in_progress = true;
|
if (defined) {
|
||||||
s = define_smacro(tok_text(smac->expansion), casesense,
|
if (smac->alias) {
|
||||||
expansion, tmpl);
|
if (smac->in_progress) {
|
||||||
smac->in_progress = false;
|
nasm_nonfatal("macro alias loop");
|
||||||
return s;
|
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);
|
smac->name = nasm_strdup(mname);
|
||||||
@ -3660,6 +3728,9 @@ static int do_directive(Token *tline, Token **output)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PP_STACKSIZE:
|
case PP_STACKSIZE:
|
||||||
|
{
|
||||||
|
const char *arg;
|
||||||
|
|
||||||
/* Directive to tell NASM what the default stack size is. The
|
/* Directive to tell NASM what the default stack size is. The
|
||||||
* default is for a 16-bit stack, and this can be overriden with
|
* default is for a 16-bit stack, and this can be overriden with
|
||||||
* %stacksize large.
|
* %stacksize large.
|
||||||
@ -3667,20 +3738,24 @@ static int do_directive(Token *tline, Token **output)
|
|||||||
tline = skip_white(tline->next);
|
tline = skip_white(tline->next);
|
||||||
if (!tline || tline->type != TOKEN_ID) {
|
if (!tline || tline->type != TOKEN_ID) {
|
||||||
nasm_nonfatal("`%s' missing size parameter", dname);
|
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 */
|
/* All subsequent ARG directives are for a 32-bit stack */
|
||||||
StackSize = 4;
|
StackSize = 4;
|
||||||
StackPointer = "ebp";
|
StackPointer = "ebp";
|
||||||
ArgOffset = 8;
|
ArgOffset = 8;
|
||||||
LocalOffset = 0;
|
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 */
|
/* All subsequent ARG directives are for a 64-bit stack */
|
||||||
StackSize = 8;
|
StackSize = 8;
|
||||||
StackPointer = "rbp";
|
StackPointer = "rbp";
|
||||||
ArgOffset = 16;
|
ArgOffset = 16;
|
||||||
LocalOffset = 0;
|
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,
|
/* All subsequent ARG directives are for a 16-bit stack,
|
||||||
* far function call.
|
* far function call.
|
||||||
*/
|
*/
|
||||||
@ -3688,7 +3763,7 @@ static int do_directive(Token *tline, Token **output)
|
|||||||
StackPointer = "bp";
|
StackPointer = "bp";
|
||||||
ArgOffset = 4;
|
ArgOffset = 4;
|
||||||
LocalOffset = 0;
|
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,
|
/* All subsequent ARG directives are for a 16-bit stack,
|
||||||
* far function call. We don't support near functions.
|
* 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);
|
nasm_nonfatal("`%s' invalid size type", dname);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case PP_ARG:
|
case PP_ARG:
|
||||||
/* TASM like ARG directive to define arguments to functions, in
|
/* TASM like ARG directive to define arguments to functions, in
|
||||||
@ -5609,15 +5685,17 @@ static SMacro *expand_one_smacro(Token ***tpp)
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TOKEN_PREPROC_Q:
|
case TOKEN_PREPROC_Q:
|
||||||
|
case TOKEN_PREPROC_SQ:
|
||||||
delete_Token(t);
|
delete_Token(t);
|
||||||
t = dup_Token(tline, mstart);
|
t = dup_Token(tline, mstart);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOKEN_PREPROC_QQ:
|
case TOKEN_PREPROC_QQ:
|
||||||
|
case TOKEN_PREPROC_SQQ:
|
||||||
{
|
{
|
||||||
size_t mlen = strlen(m->name);
|
size_t mlen = strlen(m->name);
|
||||||
size_t len;
|
size_t len;
|
||||||
char *p;
|
char *p, *from;
|
||||||
|
|
||||||
t->type = mstart->type;
|
t->type = mstart->type;
|
||||||
if (t->type == TOKEN_LOCAL_MACRO) {
|
if (t->type == TOKEN_LOCAL_MACRO) {
|
||||||
@ -5630,15 +5708,15 @@ static SMacro *expand_one_smacro(Token ***tpp)
|
|||||||
plen = pep - psp;
|
plen = pep - psp;
|
||||||
|
|
||||||
len = mlen + plen;
|
len = mlen + plen;
|
||||||
p = nasm_malloc(len + 1);
|
from = p = nasm_malloc(len + 1);
|
||||||
p = mempcpy(p, psp, plen);
|
p = mempcpy(p, psp, plen);
|
||||||
} else {
|
} else {
|
||||||
len = mlen;
|
len = mlen;
|
||||||
p = nasm_malloc(len + 1);
|
from = p = nasm_malloc(len + 1);
|
||||||
}
|
}
|
||||||
p = mempcpy(p, m->name, mlen);
|
p = mempcpy(p, m->name, mlen);
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
set_text_free(t, p, len);
|
set_text_free(t, from, len);
|
||||||
|
|
||||||
t->next = tline;
|
t->next = tline;
|
||||||
break;
|
break;
|
||||||
@ -6974,6 +7052,9 @@ static Token *pp_tokline(void)
|
|||||||
free_tlist(m->iline);
|
free_tlist(m->iline);
|
||||||
nasm_free(m->paramlen);
|
nasm_free(m->paramlen);
|
||||||
fm->in_progress = 0;
|
fm->in_progress = 0;
|
||||||
|
m->params = NULL;
|
||||||
|
m->iline = NULL;
|
||||||
|
m->paramlen = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#!/usr/bin/perl
|
#!/usr/bin/perl
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
|
use Fcntl qw(:seek);
|
||||||
use File::Find;
|
use File::Find;
|
||||||
use File::Basename;
|
use File::Basename;
|
||||||
|
|
||||||
@ -134,8 +135,9 @@ sub sort_warnings {
|
|||||||
my @warn_noall = @warnings;
|
my @warn_noall = @warnings;
|
||||||
pop @warn_noall if ($warn_noall[$#warn_noall]->{name} eq 'all');
|
pop @warn_noall if ($warn_noall[$#warn_noall]->{name} eq 'all');
|
||||||
|
|
||||||
open(my $out, '>', $outfile)
|
my $outdata;
|
||||||
or die "$0: cannot open output file $outfile: $!\n";
|
open(my $out, '>', \$outdata)
|
||||||
|
or die "$0: cannot create memory file: $!\n";
|
||||||
|
|
||||||
if ($what eq 'c') {
|
if ($what eq 'c') {
|
||||||
print $out "#include \"error.h\"\n\n";
|
print $out "#include \"error.h\"\n\n";
|
||||||
@ -273,4 +275,21 @@ if ($what eq 'c') {
|
|||||||
print $out "\\b \\i\\c{", $pfx, "} ", @doc, "\n";
|
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);
|
close($out);
|
||||||
|
12
configure.ac
12
configure.ac
@ -396,6 +396,18 @@ PA_ARG_ENABLED([werror],
|
|||||||
PA_ADD_CFLAGS([-Werror=vla])]
|
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
|
||||||
dnl Test compiler features. On some compilers, this can be affected
|
dnl Test compiler features. On some compilers, this can be affected
|
||||||
dnl by -Werror options, so run this *after* those options are added.
|
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
|
The NASM 2 series supports x86-64, and is the production version of NASM
|
||||||
since 2007.
|
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
|
\S{cl-2.15.03} Version 2.15.03
|
||||||
|
|
||||||
\b Add instructions from the Intel Instruction Set Extensions and
|
\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
|
\# Copyright 1996-2020 The NASM Authors - All Rights Reserved
|
||||||
|
\M{year}{1996-2020}
|
||||||
\# See the file AUTHORS included with the NASM distribution for
|
\# See the file AUTHORS included with the NASM distribution for
|
||||||
\# the specific copyright holders.
|
\# the specific copyright holders.
|
||||||
\#
|
\#
|
||||||
@ -36,10 +37,9 @@
|
|||||||
|
|
||||||
\M{category}{Programming}
|
\M{category}{Programming}
|
||||||
\M{title}{NASM - The Netwide Assembler}
|
\M{title}{NASM - The Netwide Assembler}
|
||||||
\M{year}{1996-2017}
|
|
||||||
\M{author}{The NASM Development Team}
|
\M{author}{The NASM Development Team}
|
||||||
\M{copyright_tail}{-- All Rights Reserved}
|
\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{summary}{This file documents NASM, the Netwide Assembler: an assembler targetting the Intel x86 series of processors, with portable source.}
|
||||||
\M{infoname}{NASM}
|
\M{infoname}{NASM}
|
||||||
\M{infofile}{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
|
Developer Manual with minimal complexity. It supports all currently
|
||||||
known x86 architectural extensions, and has strong support for macros.
|
known x86 architectural extensions, and has strong support for macros.
|
||||||
|
|
||||||
NASM also comes with a set of utilities for handling its own RDOFF2
|
\S{legal} \i{License}
|
||||||
object-file format.
|
|
||||||
|
|
||||||
\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
|
Copyright \m{year} the NASM Authors - All rights reserved.
|
||||||
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.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are
|
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{-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
|
These options can be enabled or disabled at runtime using the
|
||||||
\c{%pragma list options} directive:
|
\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\{RESZ}; the \i\c{INCBIN} command, the \i\c{EQU} command, and the
|
||||||
\i\c{TIMES} prefix.
|
\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}
|
\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
|
and \i\c{DZ} (collectively "\c{Dx}" in this documentation) are used,
|
||||||
the output file. They can be invoked in a wide range of ways:
|
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}
|
\I{floating-point}\I{character constant}\I{string constant}
|
||||||
|
|
||||||
\c db 0x55 ; just the byte 0x55
|
\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 dq 1.234567e20 ; double-precision float
|
||||||
\c dt 1.234567e20 ; extended-precision float
|
\c dt 1.234567e20 ; extended-precision float
|
||||||
|
|
||||||
\c{DT}, \c{DO}, \c{DY} and \c{DZ} do not accept \i{numeric constants}
|
\c{DT}, \c{DO}, \c{DY} and \c{DZ} do not accept integer
|
||||||
as operands.
|
\i{numeric constants} as operands.
|
||||||
|
|
||||||
\I{masmdb} Starting in NASM 2.15, a the following \i{MASM}-like features
|
\I{masmdb} Starting in NASM 2.15, a the following \i{MASM}-like features
|
||||||
have been implemented:
|
have been implemented:
|
||||||
@ -1329,6 +1329,22 @@ valid:
|
|||||||
\c dd 16 dup (0xaaaa, ?, 0xbbbbbb)
|
\c dd 16 dup (0xaaaa, ?, 0xbbbbbb)
|
||||||
\c dd 64 dup (?)
|
\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
|
\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},
|
\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:
|
For example:
|
||||||
|
|
||||||
\c %idefine Foo mov %?,%??
|
\c %imacro Foo 0
|
||||||
|
\c mov %?,%??
|
||||||
|
\c %endmacro
|
||||||
\c
|
\c
|
||||||
\c foo
|
\c foo
|
||||||
\c FOO
|
\c FOO
|
||||||
@ -2415,15 +2433,51 @@ will expand to:
|
|||||||
\c mov foo,Foo
|
\c mov foo,Foo
|
||||||
\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
|
If the tokens \c{%?} and \c{%??} are used inside a multi-line macro,
|
||||||
instruction has been used as a label in older code. For example:
|
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}
|
\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
|
\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}
|
The \c{rdf} output format produces \c{RDOFF} object files. \c{RDOFF}
|
||||||
(Relocatable Dynamic Object File Format) is a home-grown object-file
|
(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
|
manager, an RDF file dump utility, and a program which will load and
|
||||||
execute an RDF executable under Linux.
|
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
|
\S{rdflib} Requiring a Library: The \i\c{LIBRARY} Directive
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ my $r = system($gs, "-dCompatibilityLevel${o}1.3",
|
|||||||
$fpopt,
|
$fpopt,
|
||||||
"-dCompressPages${o}" . ($compress ? 'true' : 'false'),
|
"-dCompressPages${o}" . ($compress ? 'true' : 'false'),
|
||||||
"-dUseFlateCompression${o}true",
|
"-dUseFlateCompression${o}true",
|
||||||
"-c", ".setpdfwrite", "-f", $in);
|
"-f", $in);
|
||||||
exit 0 if ( !$r && -f $out );
|
exit 0 if ( !$r && -f $out );
|
||||||
|
|
||||||
# 3. pstopdf (BSD/MacOS X utility)
|
# 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
|
# another, so that \I{foobar} has the effect of \I{bazquux}, and
|
||||||
# \i{foobar} has the effect of \I{bazquux}foobar
|
# \i{foobar} has the effect of \I{bazquux}foobar
|
||||||
#
|
#
|
||||||
# Metadata
|
# Metadata/macros
|
||||||
# \M{key}{something}
|
# \M{key}{something}
|
||||||
# defines document metadata, such as authorship, title and copyright;
|
# defines document metadata, such as authorship, title and copyright;
|
||||||
# different output formats use this differently.
|
# different output formats use this differently.
|
||||||
|
# \m{key}
|
||||||
|
# insert the {something} string associated with metadata {key}
|
||||||
#
|
#
|
||||||
# Include subfile
|
# Include subfile
|
||||||
# \&{filename}
|
# \&{filename}
|
||||||
@ -270,6 +272,15 @@ sub got_para {
|
|||||||
|
|
||||||
@$pname = ();
|
@$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.
|
# Strip off _leading_ spaces, then determine type of paragraph.
|
||||||
s/^\s*//;
|
s/^\s*//;
|
||||||
$irewrite = undef;
|
$irewrite = undef;
|
||||||
@ -660,11 +671,13 @@ sub write_txt {
|
|||||||
}
|
}
|
||||||
print "$title\n";
|
print "$title\n";
|
||||||
} elsif ($ptype eq "code") {
|
} elsif ($ptype eq "code") {
|
||||||
# Code paragraph. Emit each line with a seven character indent.
|
# Code paragraph. Emit each line with a seven character indent.
|
||||||
foreach $i (@$pname) {
|
my $maxlen = 80;
|
||||||
warn "code line longer than 68 chars: $i\n" if length $i > 68;
|
foreach $i (@$pname) {
|
||||||
print ' 'x7, $i, "\n";
|
warn "code line longer than $maxlen chars: $i\n"
|
||||||
}
|
if ( length($i) > $maxlen );
|
||||||
|
print ' 'x7, $i, "\n";
|
||||||
|
}
|
||||||
} elsif ($ptype =~ /^(norm|bull|indt|bquo)$/) {
|
} elsif ($ptype =~ /^(norm|bull|indt|bquo)$/) {
|
||||||
# Ordinary paragraph, optionally indented. We wrap, with ragged
|
# Ordinary paragraph, optionally indented. We wrap, with ragged
|
||||||
# 75-char right margin and either 7 or 11 char left margin
|
# 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(fmt, list) format_func3(printf,fmt,list)
|
||||||
#define printf_func_ptr(fmt, list) format_func3_ptr(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 */
|
/* Determine probabilistically if something is a compile-time constant */
|
||||||
#ifdef HAVE___BUILTIN_CONSTANT_P
|
#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);
|
fatal_func nasm_panic_from_macro(const char *file, int line);
|
||||||
#define panic() nasm_panic_from_macro(__FILE__, __LINE__);
|
#define panic() nasm_panic_from_macro(__FILE__, __LINE__);
|
||||||
|
|
||||||
void nasm_verror(errflags severity, const char *fmt, va_list ap);
|
void vprintf_func(2) nasm_verror(errflags severity, const char *fmt, va_list ap);
|
||||||
fatal_func nasm_verror_critical(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
|
* 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_NAKED_STR, /* Unquoted string that can be re-quoted */
|
||||||
TOKEN_PREPROC_Q, /* %? */
|
TOKEN_PREPROC_Q, /* %? */
|
||||||
TOKEN_PREPROC_QQ, /* %?? */
|
TOKEN_PREPROC_QQ, /* %?? */
|
||||||
|
TOKEN_PREPROC_SQ, /* %*? */
|
||||||
|
TOKEN_PREPROC_SQQ, /* %*? */
|
||||||
TOKEN_PASTE, /* %+ */
|
TOKEN_PASTE, /* %+ */
|
||||||
TOKEN_COND_COMMA, /* %, */
|
TOKEN_COND_COMMA, /* %, */
|
||||||
TOKEN_INDIRECT, /* %[...] */
|
TOKEN_INDIRECT, /* %[...] */
|
||||||
@ -617,13 +619,14 @@ enum prefixes { /* instruction prefixes */
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum ea_flags { /* special EA flags */
|
enum ea_flags { /* special EA flags */
|
||||||
EAF_BYTEOFFS = 1, /* force offset part to byte size */
|
EAF_BYTEOFFS = 1, /* force offset part to byte size */
|
||||||
EAF_WORDOFFS = 2, /* force offset part to [d]word size */
|
EAF_WORDOFFS = 2, /* force offset part to [d]word size */
|
||||||
EAF_TIMESTWO = 4, /* really do EAX*2 not EAX+EAX */
|
EAF_TIMESTWO = 4, /* really do EAX*2 not EAX+EAX */
|
||||||
EAF_REL = 8, /* IP-relative addressing */
|
EAF_REL = 8, /* IP-relative addressing */
|
||||||
EAF_ABS = 16, /* non-IP-relative addressing */
|
EAF_ABS = 16, /* non-IP-relative addressing */
|
||||||
EAF_FSGS = 32, /* fs/gs segment override present */
|
EAF_FSGS = 32, /* fs/gs segment override present */
|
||||||
EAF_MIB = 64 /* mib operand */
|
EAF_MIB = 64, /* mib operand */
|
||||||
|
EAF_SIB = 128 /* SIB encoding obligatory */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum eval_hint { /* values for `hinttype' */
|
enum eval_hint { /* values for `hinttype' */
|
||||||
|
@ -83,9 +83,9 @@ char * safe_alloc end_with_null nasm_strcatn(const char *one, ...);
|
|||||||
* this additional storage.
|
* this additional storage.
|
||||||
*/
|
*/
|
||||||
char * safe_alloc printf_func(1, 2) nasm_asprintf(const char *fmt, ...);
|
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 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
|
* 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 *strlist_add(struct strlist *list, const char *str);
|
||||||
const struct strlist_entry * printf_func(2, 3)
|
const struct strlist_entry * printf_func(2, 3)
|
||||||
strlist_printf(struct strlist *list, const char *fmt, ...);
|
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);
|
strlist_vprintf(struct strlist *list, const char *fmt, va_list ap);
|
||||||
const struct strlist_entry *
|
const struct strlist_entry *
|
||||||
strlist_find(const struct strlist *list, const char *str);
|
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)
|
static void cv8_cleanup(void)
|
||||||
{
|
{
|
||||||
struct cv8_symbol *sym;
|
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 *symbol_sect = coff_sects[cv8_state.symbol_sect];
|
||||||
struct coff_Section *type_sect = coff_sects[cv8_state.type_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_symbol_table(symbol_sect);
|
||||||
build_type_table(type_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);
|
nasm_free(file->fullname);
|
||||||
saa_free(file->lines);
|
saa_free(file->lines);
|
||||||
free(file);
|
nasm_free(file);
|
||||||
}
|
}
|
||||||
hash_free(&cv8_state.file_hash);
|
hash_free(&cv8_state.file_hash);
|
||||||
|
|
||||||
@ -401,8 +401,7 @@ static struct source_file *register_file(const char *filename)
|
|||||||
|
|
||||||
fullpath = nasm_realpath(filename);
|
fullpath = nasm_realpath(filename);
|
||||||
|
|
||||||
file = nasm_zalloc(sizeof(*file));
|
nasm_new(file);
|
||||||
|
|
||||||
file->filename = filename;
|
file->filename = filename;
|
||||||
file->fullname = fullpath;
|
file->fullname = fullpath;
|
||||||
file->fullnamelen = strlen(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) {
|
* Alignment can be increased, but never decreased. However,
|
||||||
uint32_t sect_align_flags = coff_sects[i]->align_flags;
|
* specifying a narrower alignment is permitted and ignored.
|
||||||
|
*/
|
||||||
/* Compute the actual alignment */
|
if (align_flags > coff_sects[i]->align_flags) {
|
||||||
unsigned int align = coff_alignment(align_flags);
|
coff_sects[i]->align_flags = 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,9 +130,6 @@
|
|||||||
#ifndef OF_AS86
|
#ifndef OF_AS86
|
||||||
#define OF_AS86
|
#define OF_AS86
|
||||||
#endif
|
#endif
|
||||||
#ifndef OF_RDF2
|
|
||||||
#define OF_RDF2
|
|
||||||
#endif
|
|
||||||
#ifndef OF_IEEE
|
#ifndef OF_IEEE
|
||||||
#define OF_IEEE
|
#define OF_IEEE
|
||||||
#endif
|
#endif
|
||||||
@ -194,9 +191,6 @@
|
|||||||
#ifndef OF_AS86
|
#ifndef OF_AS86
|
||||||
#define OF_AS86
|
#define OF_AS86
|
||||||
#endif
|
#endif
|
||||||
#ifndef OF_RDF2
|
|
||||||
#define OF_RDF2
|
|
||||||
#endif
|
|
||||||
#ifndef OF_IEEE
|
#ifndef OF_IEEE
|
||||||
#define OF_IEEE
|
#define OF_IEEE
|
||||||
#endif
|
#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 >> 16) & 0xFF);
|
||||||
ieee_write_byte(seg, (data >> 24) & 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];
|
char buffer[256];
|
||||||
int i, l;
|
size_t i, l;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
l = vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||||
l = strlen(buffer);
|
nasm_assert(l < sizeof(buffer));
|
||||||
for (i = 0; i < l; i++)
|
for (i = 0; i < l; i++)
|
||||||
if ((uint8_t)buffer[i] > 31)
|
if ((uint8_t)buffer[i] > 31)
|
||||||
checksum += buffer[i];
|
checksum += buffer[i];
|
||||||
|
@ -424,6 +424,12 @@ static ObjRecord *obj_name(ObjRecord * orp, const char *name)
|
|||||||
int len = strlen(name);
|
int len = strlen(name);
|
||||||
uint8_t *ptr;
|
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);
|
orp = obj_check(orp, len + 1);
|
||||||
ptr = orp->buf + orp->used;
|
ptr = orp->buf + orp->used;
|
||||||
*ptr++ = len;
|
*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_("NOLONG", "Not available in long mode");
|
||||||
if_("LONG", "Long mode");
|
if_("LONG", "Long mode");
|
||||||
if_("NOHLE", "HLE prefixes forbidden");
|
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_("BND", "BND (0xF2) prefix available");
|
||||||
if_("UNDOC", "Undocumented");
|
if_("UNDOC", "Undocumented");
|
||||||
if_("HLE", "HLE prefixed");
|
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
|
#!/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
|
## See the file AUTHORS included with the NASM distribution for
|
||||||
## the specific copyright holders.
|
## the specific copyright holders.
|
||||||
##
|
##
|
||||||
@ -444,7 +444,7 @@ sub format_insn($$$$$) {
|
|||||||
my $nd = 0;
|
my $nd = 0;
|
||||||
my ($num, $flagsindex);
|
my ($num, $flagsindex);
|
||||||
my @bytecode;
|
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";
|
return (undef, undef) if $operands eq "ignore";
|
||||||
|
|
||||||
@ -452,9 +452,11 @@ sub format_insn($$$$$) {
|
|||||||
$operands =~ s/\*//g;
|
$operands =~ s/\*//g;
|
||||||
$operands =~ s/:/|colon,/g;
|
$operands =~ s/:/|colon,/g;
|
||||||
@ops = ();
|
@ops = ();
|
||||||
|
@opsize = ();
|
||||||
@decos = ();
|
@decos = ();
|
||||||
if ($operands ne 'void') {
|
if ($operands ne 'void') {
|
||||||
foreach $op (split(/,/, $operands)) {
|
foreach $op (split(/,/, $operands)) {
|
||||||
|
my $opsz = 0;
|
||||||
@opx = ();
|
@opx = ();
|
||||||
@opevex = ();
|
@opevex = ();
|
||||||
foreach $opp (split(/\|/, $op)) {
|
foreach $opp (split(/\|/, $op)) {
|
||||||
@ -465,6 +467,7 @@ sub format_insn($$$$$) {
|
|||||||
|
|
||||||
if ($opp =~ s/(?<!\d)(8|16|32|64|80|128|256|512)$//) {
|
if ($opp =~ s/(?<!\d)(8|16|32|64|80|128|256|512)$//) {
|
||||||
push(@oppx, "bits$1");
|
push(@oppx, "bits$1");
|
||||||
|
$opsz = $1 + 0;
|
||||||
}
|
}
|
||||||
$opp =~ s/^mem$/memory/;
|
$opp =~ s/^mem$/memory/;
|
||||||
$opp =~ s/^memory_offs$/mem_offs/;
|
$opp =~ s/^memory_offs$/mem_offs/;
|
||||||
@ -481,6 +484,7 @@ sub format_insn($$$$$) {
|
|||||||
}
|
}
|
||||||
$op = join('|', @opx);
|
$op = join('|', @opx);
|
||||||
push(@ops, $op);
|
push(@ops, $op);
|
||||||
|
push(@opsize, $opsz);
|
||||||
push(@decos, (@opevex ? join('|', @opevex) : '0'));
|
push(@decos, (@opevex ? join('|', @opevex) : '0'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -488,6 +492,7 @@ sub format_insn($$$$$) {
|
|||||||
$num = scalar(@ops);
|
$num = scalar(@ops);
|
||||||
while (scalar(@ops) < $MAX_OPERANDS) {
|
while (scalar(@ops) < $MAX_OPERANDS) {
|
||||||
push(@ops, '0');
|
push(@ops, '0');
|
||||||
|
push(@opsize, 0);
|
||||||
push(@decos, '0');
|
push(@decos, '0');
|
||||||
}
|
}
|
||||||
$operands = join(',', @ops);
|
$operands = join(',', @ops);
|
||||||
@ -499,16 +504,17 @@ sub format_insn($$$$$) {
|
|||||||
}
|
}
|
||||||
$decorators =~ tr/a-z/A-Z/;
|
$decorators =~ tr/a-z/A-Z/;
|
||||||
|
|
||||||
|
# Remember if we have an ARx flag
|
||||||
|
my $arx = undef;
|
||||||
|
|
||||||
# expand and uniqify the flags
|
# expand and uniqify the flags
|
||||||
my %flags;
|
my %flags;
|
||||||
foreach my $flag (split(',', $flags)) {
|
foreach my $flag (split(',', $flags)) {
|
||||||
|
next if ($flag eq '');
|
||||||
|
|
||||||
if ($flag eq 'ND') {
|
if ($flag eq 'ND') {
|
||||||
$nd = 1;
|
$nd = 1;
|
||||||
} elsif ($flag eq 'X64') {
|
} else {
|
||||||
# X64 is shorthand for "LONG,X86_64"
|
|
||||||
$flags{'LONG'}++;
|
|
||||||
$flags{'X86_64'}++;
|
|
||||||
} elsif ($flag ne '') {
|
|
||||||
$flags{$flag}++;
|
$flags{$flag}++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -516,6 +522,10 @@ sub format_insn($$$$$) {
|
|||||||
# These flags imply OBSOLETE
|
# These flags imply OBSOLETE
|
||||||
$flags{'OBSOLETE'}++;
|
$flags{'OBSOLETE'}++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($flag =~ /^AR([0-9]+)$/) {
|
||||||
|
$arx = $1+0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($codes =~ /evex\./) {
|
if ($codes =~ /evex\./) {
|
||||||
@ -524,8 +534,41 @@ sub format_insn($$$$$) {
|
|||||||
$flags{'VEX'}++;
|
$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);
|
$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);
|
@bytecode = (decodify($codes, $relax), 0);
|
||||||
push(@bytecode_list, [@bytecode]);
|
push(@bytecode_list, [@bytecode]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user