Merge branch 'nasm-2.14.xx'

* nasm-2.14.xx: (83 commits)
  NASM 2.14rc16
  doc: Update changes
  preproc: expand_smacro -- Fix nil dereference on error path
  eval: Eliminate division by zero
  doc: Update changes
  opflags: Convert is_class and is_reg_class to helpers
  preproc: Fix out of range access in expand mmacro
  doc: Update changes
  parser: Fix sigsegv on certain equ instruction parsing
  labels: Make sure nil label is never passed
  labels: Don't nil dereference if no label provided
  macho: Add warning message in macho_output()
  macho/reloc: Fix addr size sensitive conditions
  macho/reloc: Fix macho_output() to get the offset adjustments by add_reloc()
  macho/reloc: Fixed offset adjustment in add_reloc()
  macho/reloc: Allow absolute relocation when forcing a symbol reference
  macho/reloc: Adjust SUB relocation information
  macho/reloc: Fixed in handling GOT/GOTLOAD/TLV relocations
  macho/reloc: Simplified relocation for REL/BRANCH
  macho/sym: Record initial symbol number always
  ...

Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
This commit is contained in:
Cyrill Gorcunov 2018-10-15 22:58:13 +03:00
commit f7b44f6092
36 changed files with 884 additions and 252 deletions

1
.gitignore vendored
View File

@ -40,6 +40,7 @@ TAGS
/*.1
/Makefile
/asm/directbl.c
/asm/directbl.h
/asm/directiv.h
/asm/pptok.c
/asm/pptok.h

View File

@ -50,7 +50,7 @@ XMLTO = @XMLTO@
MAKENSIS = makensis
MKDIR = mkdir
MKDIR = mkdir -p
RM_F = rm -f
RM_RF = rm -rf
LN_S = @LN_S@
@ -67,7 +67,7 @@ ifeq ($(TRACE),1)
endif
.SUFFIXES:
.SUFFIXES: .c .i .s .$(O) .$(A) $(X) .1 .txt .xml
.SUFFIXES: $(X) .$(O) .$(A) .xml .1 .c .i .s .txt
.PHONY: all doc rdf install clean distclean cleaner spotless install_rdf test
.PHONY: install_doc everything install_everything strip perlreq dist tags TAGS
@ -277,6 +277,13 @@ asm/directbl.c: asm/directiv.dat nasmlib/perfhash.pl perllib/phash.ph
perlreq: $(PERLREQ)
# This rule is only used for RDOFF
.$(O)$(X):
$(CC) $(ALL_CFLAGS) -o $@ $< $(LDFLAGS) $(RDFLIB) $(NASMLIB) $(LIBS)
RDFLN = cd rdoff && ln -s
RDFLNPFX =
#-- Begin RDOFF Shared Rules --#
RDFLIBOBJ = rdoff/rdoff.$(O) rdoff/rdfload.$(O) rdoff/symtab.$(O) \
@ -291,31 +298,23 @@ RDF2BINLINKS = rdoff/rdf2com$(X) rdoff/rdf2ith$(X) \
RDFLIB = rdoff/librdoff.$(A)
RDFLIBS = $(RDFLIB) $(NASMLIB)
# This rule is only used for rdoff, to allow common rules
MAKERDF = $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $< $(RDFLIB) $(NASMLIB) $(LIBS)
rdoff/rdfdump$(X): rdoff/rdfdump.$(O) $(RDFLIBS)
$(MAKERDF)
rdoff/ldrdf$(X): rdoff/ldrdf.$(O) $(RDFLIBS)
$(MAKERDF)
rdoff/rdx$(X): rdoff/rdx.$(O) $(RDFLIBS)
$(MAKERDF)
rdoff/rdflib$(X): rdoff/rdflib.$(O) $(RDFLIBS)
$(MAKERDF)
rdoff/rdf2bin$(X): rdoff/rdf2bin.$(O) $(RDFLIBS)
$(MAKERDF)
rdoff/rdf2com$(X): rdoff/rdf2bin$(X)
$(RM_F) rdoff/rdf2com$(X)
cd rdoff && $(LN_S) rdf2bin$(X) rdf2com$(X)
$(RDFLN) $(RDFLNPFX)rdf2bin$(X) $(RDFLNPFX)rdf2com$(X)
rdoff/rdf2ith$(X): rdoff/rdf2bin$(X)
$(RM_F) rdoff/rdf2ith$(X)
cd rdoff && $(LN_S) rdf2bin$(X) rdf2ith$(X)
$(RDFLN) $(RDFLNPFX)rdf2bin$(X) $(RDFLNPFX)rdf2ith$(X)
rdoff/rdf2ihx$(X): rdoff/rdf2bin$(X)
$(RM_F) rdoff/rdf2ihx$(X)
cd rdoff && $(LN_S) rdf2bin$(X) rdf2ihx$(X)
$(RDFLN) $(RDFLNPFX)rdf2bin$(X) $(RDFLNPFX)rdf2ihx$(X)
rdoff/rdf2srec$(X): rdoff/rdf2bin$(X)
$(RM_F) rdoff/rdf2srec$(X)
cd rdoff && $(LN_S) rdf2bin$(X) rdf2srec$(X)
$(RDFLN) $(RDFLNPFX)rdf2bin$(X) $(RDFLNPFX)rdf2srec$(X)
#-- End RDOFF Shared Rules --#
@ -345,10 +344,10 @@ nsis: nsis/nasm.nsi nsis/arch.nsh nsis/version.nsh
manpages: nasm.1 ndisasm.1
install: nasm$(X) ndisasm$(X)
$(MKDIR) -p $(DESTDIR)$(bindir)
$(MKDIR) $(DESTDIR)$(bindir)
$(INSTALL_PROGRAM) nasm$(X) $(DESTDIR)$(bindir)/nasm$(X)
$(INSTALL_PROGRAM) ndisasm$(X) $(DESTDIR)$(bindir)/ndisasm$(X)
$(MKDIR) -p $(DESTDIR)$(mandir)/man1
$(MKDIR) $(DESTDIR)$(mandir)/man1
$(INSTALL_DATA) $(srcdir)/nasm.1 $(DESTDIR)$(mandir)/man1/nasm.1
$(INSTALL_DATA) $(srcdir)/ndisasm.1 $(DESTDIR)$(mandir)/man1/ndisasm.1
@ -397,7 +396,7 @@ cscope:
cscope -b -f cscope.out
rdf_install install_rdf install_rdoff:
$(MKDIR) -p $(DESTDIR)$(bindir)
$(MKDIR) $(DESTDIR)$(bindir)
for f in $(RDFPROGS); do \
$(INSTALL_PROGRAM) "$$f" '$(DESTDIR)$(bindir)'/ ; \
done
@ -406,7 +405,7 @@ rdf_install install_rdf install_rdoff:
bn=`basename "$$f"` && $(RM_F) "$$bn" && \
$(LN_S) rdf2bin$(X) "$$bn" ; \
done
$(MKDIR) -p $(DESTDIR)$(mandir)/man1
$(MKDIR) $(DESTDIR)$(mandir)/man1
$(INSTALL_DATA) $(srcdir)/rdoff/*.1 $(DESTDIR)$(mandir)/man1/
doc:

View File

@ -46,7 +46,7 @@ RUNPERL = $(PERL) $(PERLFLAGS)
MAKENSIS = makensis
RM_F = del /f
RM_F = -del /f
LN_S = copy
# Binary suffixes
@ -54,15 +54,11 @@ O = obj
A = lib
X = .exe
.SUFFIXES:
.SUFFIXES: .c .i .s .$(O) .$(A) .exe .1 .man
.SUFFIXES: $(X) .$(A) .$(O) .c .i .s .1 .man
.c.obj:
$(CC) /c $(ALL_CFLAGS) /Fo$@ $<
# This rule is only used for rdoff
.obj.exe:
$(CC) $(ALL_CFLAGS) /Fe$@ $< $(LDFLAGS) $(RDFLIB) $(NASMLIB) $(LIBS)
#-- Begin File Lists --#
# Edit in Makefile.in, not here!
NASM = asm\nasm.$(O)
@ -252,6 +248,13 @@ asm\directbl.c: asm\directiv.dat nasmlib\perfhash.pl perllib\phash.ph
perlreq: $(PERLREQ)
# This rule is only used for RDOFF
.obj.exe:
$(CC) /Fe$@ $< $(LDFLAGS) $(RDFLIB) $(NASMLIB) $(LIBS)
RDFLN = copy
RDFLNPFX = rdoff^\
#-- Begin RDOFF Shared Rules --#
# Edit in Makefile.in, not here!
@ -267,31 +270,23 @@ RDF2BINLINKS = rdoff\rdf2com$(X) rdoff\rdf2ith$(X) \
RDFLIB = rdoff\librdoff.$(A)
RDFLIBS = $(RDFLIB) $(NASMLIB)
# This rule is only used for rdoff, to allow common rules
MAKERDF = $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $< $(RDFLIB) $(NASMLIB) $(LIBS)
rdoff\rdfdump$(X): rdoff\rdfdump.$(O) $(RDFLIBS)
$(MAKERDF)
rdoff\ldrdf$(X): rdoff\ldrdf.$(O) $(RDFLIBS)
$(MAKERDF)
rdoff\rdx$(X): rdoff\rdx.$(O) $(RDFLIBS)
$(MAKERDF)
rdoff\rdflib$(X): rdoff\rdflib.$(O) $(RDFLIBS)
$(MAKERDF)
rdoff\rdf2bin$(X): rdoff\rdf2bin.$(O) $(RDFLIBS)
$(MAKERDF)
rdoff\rdf2com$(X): rdoff\rdf2bin$(X)
$(RM_F) rdoff\rdf2com$(X)
cd rdoff && $(LN_S) rdf2bin$(X) rdf2com$(X)
$(RDFLN) $(RDFLNPFX)rdf2bin$(X) $(RDFLNPFX)rdf2com$(X)
rdoff\rdf2ith$(X): rdoff\rdf2bin$(X)
$(RM_F) rdoff\rdf2ith$(X)
cd rdoff && $(LN_S) rdf2bin$(X) rdf2ith$(X)
$(RDFLN) $(RDFLNPFX)rdf2bin$(X) $(RDFLNPFX)rdf2ith$(X)
rdoff\rdf2ihx$(X): rdoff\rdf2bin$(X)
$(RM_F) rdoff\rdf2ihx$(X)
cd rdoff && $(LN_S) rdf2bin$(X) rdf2ihx$(X)
$(RDFLN) $(RDFLNPFX)rdf2bin$(X) $(RDFLNPFX)rdf2ihx$(X)
rdoff\rdf2srec$(X): rdoff\rdf2bin$(X)
$(RM_F) rdoff\rdf2srec$(X)
cd rdoff && $(LN_S) rdf2bin$(X) rdf2srec$(X)
$(RDFLN) $(RDFLNPFX)rdf2bin$(X) $(RDFLNPFX)rdf2srec$(X)
#-- End RDOFF Shared Rules --#
@ -384,21 +379,21 @@ dep: msvc.dep
# Include and/or generate msvc.dep as needed. This is too complex to
# use the include-command feature, but we can open-code it here.
!IF $(EXTERNAL_DEPENDENCIES) == 1
!IFDEF MKDEP
MKDEP=0
!IF $(EXTERNAL_DEPENDENCIES) == 1 && $(MKDEP) == 0
!IF EXISTS(msvc.dep)
!INCLUDE msvc.dep
!ENDIF
!ELSEIF [$(MAKE) /c MKDEP=1 /f Mkfiles\msvc.mak msvc.dep] == 0
!INCLUDE msvc.dep
!ELSE
!ERROR Unable to rebuild dependencies file msvc.dep
!ENDIF
!ENDIF
#-- Magic hints to mkdep.pl --#
# @object-ending: ".$(O)"
# @path-separator: "\"
# @exclude: "config/config.h"
# @exclude: "config\config.h"
# @external: "msvc.dep"
# @selfrule: "1"
#-- Everything below is generated by mkdep.pl - do not edit --#

View File

@ -208,6 +208,8 @@ enum match_result {
MERR_ENCMISMATCH,
MERR_BADBND,
MERR_BADREPNE,
MERR_REGSETSIZE,
MERR_REGSET,
/*
* Matching success; the conditional ones first
*/
@ -537,9 +539,9 @@ static bool jmp_match(int32_t segment, int64_t offset, int bits,
if (((c & ~1) != 0370) || (ins->oprs[0].type & STRICT))
return false;
if (!optimizing)
if (!optimizing.level || (optimizing.flag & OPTIM_DISABLE_JMP_MATCH))
return false;
if (optimizing < 0 && c == 0371)
if (optimizing.level < 0 && c == 0371)
return false;
isize = calcsize(segment, offset, bits, ins, temp);
@ -803,6 +805,12 @@ int64_t assemble(int32_t segment, int64_t start, int bits, insn *instruction)
(has_prefix(instruction, PPS_REP, P_REPNE) ?
"repne" : "repnz"));
break;
case MERR_REGSETSIZE:
nasm_error(ERR_NONFATAL, "invalid register set size");
break;
case MERR_REGSET:
nasm_error(ERR_NONFATAL, "register set not valid for operand");
break;
default:
nasm_error(ERR_NONFATAL,
"invalid combination of opcode and operands");
@ -2191,7 +2199,7 @@ static enum match_result matches(const struct itemplate *itemp,
/*
* Is it legal?
*/
if (!(optimizing > 0) && itemp_has(itemp, IF_OPT))
if (!(optimizing.level > 0) && itemp_has(itemp, IF_OPT))
return MERR_INVALOP;
/*
@ -2334,9 +2342,14 @@ static enum match_result matches(const struct itemplate *itemp,
if (~ideco & deco & (Z_MASK|STATICRND_MASK|SAE_MASK))
return MERR_DECONOTHERE;
if (itemp->opd[i] & ~type & ~SIZE_MASK) {
if (itemp->opd[i] & ~type & ~(SIZE_MASK|REGSET_MASK))
return MERR_INVALOP;
} else if (template_opsize) {
if (~itemp->opd[i] & type & REGSET_MASK)
return (itemp->opd[i] & REGSET_MASK)
? MERR_REGSETSIZE : MERR_REGSET;
if (template_opsize) {
if (template_opsize != insn_opsize) {
if (insn_opsize) {
return MERR_INVALOP;

View File

@ -399,6 +399,7 @@ bool process_directives(char *directive)
"in pass two");
in_absolute = true;
location.segment = NO_SEG;
location.offset = absolute.offset;
break;
}

View File

@ -69,6 +69,7 @@ const struct warning warnings[ERR_WARN_ALL+1] = {
{"not-my-pragma", "%pragma not applicable to this compilation", false},
{"unknown-warning", "unknown warning in -W/-w or warning directive", false},
{"negative-rep", "regative %rep count", true},
{"phase", "phase error during stabilization", false},
/* THIS ENTRY MUST COME LAST */
{"all", "all possible warnings", false}

View File

@ -585,7 +585,7 @@ static expr *expr5(int critical)
" scalar values");
return NULL;
}
if (j != '*' && !is_unknown(f) && reloc_value(f) == 0) {
if (j != '*' && !is_just_unknown(f) && reloc_value(f) == 0) {
nasm_error(ERR_NONFATAL, "division by zero");
return NULL;
}

View File

@ -182,7 +182,7 @@ static int32_t read_exponent(const char *string, int32_t max)
} else if (*string == '_') {
/* do nothing */
} else {
nasm_error(ERR_NONFATAL|ERR_PASS1,
nasm_error(ERR_NONFATAL,
"invalid character in floating-point constant %s: '%c'",
"exponent", *string);
return INT32_MAX;
@ -219,7 +219,7 @@ static bool ieee_flconvert(const char *string, fp_limb *mant,
if (!seendot) {
seendot = true;
} else {
nasm_error(ERR_NONFATAL|ERR_PASS1,
nasm_error(ERR_NONFATAL,
"too many periods in floating-point constant");
return false;
}
@ -234,7 +234,7 @@ static bool ieee_flconvert(const char *string, fp_limb *mant,
*p++ = *string - '0';
} else {
if (!warned) {
nasm_error(ERR_WARNING|ERR_WARN_FL_TOOLONG|ERR_PASS1,
nasm_error(ERR_WARNING|ERR_WARN_FL_TOOLONG|ERR_PASS2,
"floating-point constant significand contains "
"more than %i digits", MANT_DIGITS);
warned = true;
@ -247,7 +247,7 @@ static bool ieee_flconvert(const char *string, fp_limb *mant,
} else if (*string == '_') {
/* do nothing */
} else {
nasm_error(ERR_NONFATAL|ERR_PASS1,
nasm_error(ERR_NONFATAL|ERR_PASS2,
"invalid character in floating-point constant %s: '%c'",
"significand", *string);
return false;
@ -533,7 +533,7 @@ static bool ieee_flconvert_bin(const char *string, int bits,
if (!seendot)
seendot = true;
else {
nasm_error(ERR_NONFATAL|ERR_PASS1,
nasm_error(ERR_NONFATAL,
"too many periods in floating-point constant");
return false;
}
@ -575,7 +575,7 @@ static bool ieee_flconvert_bin(const char *string, int bits,
} else if (c == '_') {
/* ignore */
} else {
nasm_error(ERR_NONFATAL|ERR_PASS1,
nasm_error(ERR_NONFATAL,
"floating-point constant: `%c' is invalid character", c);
return false;
}
@ -608,6 +608,8 @@ static void ieee_shr(fp_limb *mant, int i)
if (offs)
for (j = MANT_LIMBS-1; j >= offs; j--)
mant[j] = mant[j-offs];
} else if (MANT_LIMBS-1-offs < 0) {
j = MANT_LIMBS-1;
} else {
n = mant[MANT_LIMBS-1-offs] >> sr;
for (j = MANT_LIMBS-1; j > offs; j--) {
@ -673,7 +675,7 @@ static int to_packed_bcd(const char *str, const char *p,
int tv = -1;
if (fmt != &ieee_80) {
nasm_error(ERR_NONFATAL|ERR_PASS1,
nasm_error(ERR_NONFATAL,
"packed BCD requires an 80-bit format");
return 0;
}
@ -683,7 +685,7 @@ static int to_packed_bcd(const char *str, const char *p,
if (c >= '0' && c <= '9') {
if (tv < 0) {
if (n == 9) {
nasm_error(ERR_WARNING|ERR_PASS1,
nasm_error(ERR_WARNING|ERR_PASS2,
"packed BCD truncated to 18 digits");
}
tv = c-'0';
@ -696,7 +698,7 @@ static int to_packed_bcd(const char *str, const char *p,
} else if (c == '_') {
/* do nothing */
} else {
nasm_error(ERR_NONFATAL|ERR_PASS1,
nasm_error(ERR_NONFATAL,
"invalid character `%c' in packed BCD constant", c);
return 0;
}
@ -757,7 +759,7 @@ static int to_float(const char *str, int s, uint8_t *result,
type = FL_INFINITY;
break;
default:
nasm_error(ERR_NONFATAL|ERR_PASS1,
nasm_error(ERR_NONFATAL,
"internal error: unknown FP constant token `%s'\n", str);
type = FL_QNAN;
break;
@ -805,7 +807,7 @@ static int to_float(const char *str, int s, uint8_t *result,
type = FL_NORMAL;
} else if (exponent > 0) {
if (pass0 == 1)
nasm_error(ERR_WARNING|ERR_WARN_FL_OVERFLOW|ERR_PASS1,
nasm_error(ERR_WARNING|ERR_WARN_FL_OVERFLOW|ERR_PASS2,
"overflow in floating-point constant");
type = FL_INFINITY;
} else {
@ -840,11 +842,11 @@ static int to_float(const char *str, int s, uint8_t *result,
} else {
if (daz || is_zero(mant)) {
/* Flush denormals to zero */
nasm_error(ERR_WARNING|ERR_WARN_FL_UNDERFLOW|ERR_PASS1,
nasm_error(ERR_WARNING|ERR_WARN_FL_UNDERFLOW|ERR_PASS2,
"underflow in floating-point constant");
goto zero;
} else {
nasm_error(ERR_WARNING|ERR_WARN_FL_DENORM|ERR_PASS1,
nasm_error(ERR_WARNING|ERR_WARN_FL_DENORM|ERR_PASS2,
"denormal floating-point constant");
}
}
@ -860,7 +862,7 @@ static int to_float(const char *str, int s, uint8_t *result,
ieee_shr(mant, 1);
exponent++;
if (exponent >= (expmax << 1)-1) {
nasm_error(ERR_WARNING|ERR_WARN_FL_OVERFLOW|ERR_PASS1,
nasm_error(ERR_WARNING|ERR_WARN_FL_OVERFLOW|ERR_PASS2,
"overflow in floating-point constant");
type = FL_INFINITY;
goto overflow;

View File

@ -72,6 +72,21 @@ static bool ismagic(const char *l)
return l[0] == '.' && l[1] == '.' && l[2] != '@';
}
/*
* Return true if we should update the local label base
* as a result of this symbol. We must exclude local labels
* as well as any kind of special labels, including ..@ ones.
*/
static bool set_prevlabel(const char *l)
{
if (tasm_compatible_mode) {
if (l[0] == '@' && l[1] == '@')
return false;
}
return l[0] != '.';
}
#define LABEL_BLOCK 128 /* no. of labels/block */
#define LBLK_SIZE (LABEL_BLOCK * sizeof(union label))
@ -146,7 +161,7 @@ static void out_symdef(union label *lptr)
case LBL_EXTERN:
case LBL_COMMON:
if (lptr->defn.special)
ofmt->symdef(lptr->defn.label, 0, 0, 3, lptr->defn.special);
ofmt->symdef(lptr->defn.mangled, 0, 0, 3, lptr->defn.special);
break;
default:
break;
@ -160,6 +175,7 @@ static void out_symdef(union label *lptr)
/* Clean up this hack... */
switch(lptr->defn.type) {
case LBL_GLOBAL:
case LBL_EXTERN:
backend_type = 1;
backend_offset = lptr->defn.offset;
break;
@ -203,6 +219,8 @@ static union label *find_label(const char *label, bool create, bool *created)
char *label_str = NULL;
struct hash_insert ip;
nasm_assert(label != NULL);
if (islocal(label))
label = label_str = nasm_strcat(prevlabel, label);
@ -336,15 +354,23 @@ handle_herelabel(union label *lptr, int32_t *segment, int64_t *offset)
if (oldseg == location.segment && *offset == location.offset) {
/* This label is defined at this location */
int32_t newseg;
bool copyoffset = false;
nasm_assert(lptr->defn.mangled);
newseg = ofmt->herelabel(lptr->defn.mangled, lptr->defn.type,
oldseg, &lptr->defn.subsection);
oldseg, &lptr->defn.subsection, &copyoffset);
if (likely(newseg == oldseg))
return;
*segment = newseg;
*offset = switch_segment(newseg);
if (copyoffset) {
/* Maintain the offset from the old to the new segment */
switch_segment(newseg);
location.offset = *offset;
} else {
/* Keep a separate offset for the new segment */
*offset = switch_segment(newseg);
}
}
}
@ -383,7 +409,7 @@ static bool declare_label_lptr(union label *lptr,
type == LBL_EXTERN) {
if (!lptr->defn.special)
lptr->defn.special = perm_copy(special);
return true;
return false; /* Don't call define_label() after this! */
}
nasm_error(ERR_NONFATAL, "symbol `%s' declared both as %s and %s",
@ -394,10 +420,7 @@ static bool declare_label_lptr(union label *lptr,
bool declare_label(const char *label, enum label_type type, const char *special)
{
union label *lptr;
bool created;
lptr = find_label(label, true, &created);
union label *lptr = find_label(label, true, NULL);
return declare_label_lptr(lptr, type, special);
}
@ -419,13 +442,14 @@ void define_label(const char *label, int32_t segment,
*/
lptr = find_label(label, true, &created);
if (pass0 > 1) {
if (created)
nasm_error(ERR_WARNING, "label `%s' defined on pass two", label);
}
if (!segment)
if (segment) {
/* We are actually defining this label */
if (lptr->defn.type == LBL_EXTERN) /* auto-promote EXTERN to GLOBAL */
lptr->defn.type = LBL_GLOBAL;
} else {
/* It's a pseudo-segment (extern, common) */
segment = lptr->defn.segment ? lptr->defn.segment : seg_alloc();
}
if (lptr->defn.defined || lptr->defn.type == LBL_BACKEND) {
/* We have seen this on at least one previous pass */
@ -436,9 +460,8 @@ void define_label(const char *label, int32_t segment,
if (ismagic(label) && lptr->defn.type == LBL_LOCAL)
lptr->defn.type = LBL_SPECIAL;
if (!islocal(label) && normal) {
if (set_prevlabel(label) && normal)
prevlabel = lptr->defn.label;
}
if (lptr->defn.type == LBL_COMMON) {
size = offset;
@ -447,7 +470,8 @@ void define_label(const char *label, int32_t segment,
size = 0; /* This is a hack... */
}
changed = !lptr->defn.defined || lptr->defn.segment != segment ||
changed = created || !lptr->defn.defined ||
lptr->defn.segment != segment ||
lptr->defn.offset != offset || lptr->defn.size != size;
global_offset_changed += changed;
@ -456,9 +480,11 @@ void define_label(const char *label, int32_t segment,
* special case, LBL_SPECIAL symbols are allowed to be changed
* even during the last pass.
*/
if (changed && pass0 == 2 && lptr->defn.type != LBL_SPECIAL)
nasm_error(ERR_WARNING, "label `%s' changed during code generation",
lptr->defn.label);
if (changed && pass0 > 1 && lptr->defn.type != LBL_SPECIAL) {
nasm_error(ERR_WARNING, "label `%s' %s during code generation",
lptr->defn.label,
created ? "defined" : "changed");
}
lptr->defn.segment = segment;
lptr->defn.offset = offset;

View File

@ -117,7 +117,8 @@ const struct dfmt *dfmt;
static FILE *error_file; /* Where to write error messages */
FILE *ofile = NULL;
int optimizing = MAX_OPTIMIZE; /* number of optimization passes to take */
struct optimization optimizing =
{ MAX_OPTIMIZE, OPTIM_ALL_ENABLED }; /* number of optimization passes to take */
static int cmd_sb = 16; /* by default */
iflag_t cpu;
@ -424,6 +425,13 @@ int main(int argc, char **argv)
tolower_init();
src_init();
/*
* We must call init_labels() before the command line parsing,
* because we may be setting prefixes/suffixes from the command
* line.
*/
init_labels();
offsets = raa_init();
forwrefs = saa_init((int32_t)sizeof(struct forwrefinfo));
@ -473,9 +481,15 @@ int main(int argc, char **argv)
if (ofmt->stdmac)
preproc->extra_stdmac(ofmt->stdmac);
/* no output file name? */
if (!outname)
outname = filename_set_extension(inname, ofmt->extension);
/*
* If no output file name provided and this
* is a preprocess mode, we're perfectly
* fine to output into stdout.
*/
if (!outname) {
if (!(operating_mode & OP_PREPROCESS))
outname = filename_set_extension(inname, ofmt->extension);
}
/* define some macros dependent of command-line */
define_macros_late();
@ -553,13 +567,6 @@ int main(int argc, char **argv)
nasm_fatal_fl(ERR_NOFILE,
"unable to open output file `%s'", outname);
/*
* We must call init_labels() before ofmt->init() since
* some object formats will want to define labels in their
* init routines. (eg OS/2 defines the FLAT group)
*/
init_labels();
ofmt->init();
dfmt->init();
@ -867,7 +874,7 @@ static bool process_arg(char *p, char *q, int pass)
if (!*param) {
/* Naked -O == -Ox */
optimizing = MAX_OPTIMIZE;
optimizing.level = MAX_OPTIMIZE;
} else {
while (*param) {
switch (*param) {
@ -875,12 +882,12 @@ static bool process_arg(char *p, char *q, int pass)
case '5': case '6': case '7': case '8': case '9':
opt = strtoul(param, &param, 10);
/* -O0 -> optimizing == -1, 0.98 behaviour */
/* -O1 -> optimizing == 0, 0.98.09 behaviour */
/* -O0 -> optimizing.level == -1, 0.98 behaviour */
/* -O1 -> optimizing.level == 0, 0.98.09 behaviour */
if (opt < 2)
optimizing = opt - 1;
optimizing.level = opt - 1;
else
optimizing = opt;
optimizing.level = opt;
break;
case 'v':
@ -891,7 +898,7 @@ static bool process_arg(char *p, char *q, int pass)
case 'x':
param++;
optimizing = MAX_OPTIMIZE;
optimizing.level = MAX_OPTIMIZE;
break;
default:
@ -900,8 +907,8 @@ static bool process_arg(char *p, char *q, int pass)
break;
}
}
if (optimizing > MAX_OPTIMIZE)
optimizing = MAX_OPTIMIZE;
if (optimizing.level > MAX_OPTIMIZE)
optimizing.level = MAX_OPTIMIZE;
}
}
break;
@ -1434,7 +1441,7 @@ static void assemble_file(const char *fname, StrList **depend_ptr)
while ((line = preproc->getline())) {
if (++globallineno > nasm_limit[LIMIT_LINES])
nasm_fatal("overall line count exceeds the maximum %"PRId64"\n",
nasm_limit[LIMIT_LINES]);
nasm_limit[LIMIT_LINES]);
/*
* Here we parse our directives; this is not handled by the
@ -1446,7 +1453,7 @@ static void assemble_file(const char *fname, StrList **depend_ptr)
/* Not a directive, or even something that starts with [ */
parse_line(pass1, line, &output_ins);
if (optimizing > 0) {
if (optimizing.level > 0) {
if (forwref != NULL && globallineno == forwref->lineno) {
output_ins.forw_ref = true;
do {
@ -1472,13 +1479,11 @@ static void assemble_file(const char *fname, StrList **depend_ptr)
/* forw_ref */
if (output_ins.opcode == I_EQU) {
if (!output_ins.label)
nasm_error(ERR_NONFATAL,
"EQU not preceded by label");
if (output_ins.operands == 1 &&
(output_ins.oprs[0].type & IMMEDIATE) &&
output_ins.oprs[0].wrt == NO_SEG) {
if (!output_ins.label) {
nasm_error(ERR_NONFATAL, "EQU not preceded by label");
} else if (output_ins.operands == 1 &&
(output_ins.oprs[0].type & IMMEDIATE) &&
output_ins.oprs[0].wrt == NO_SEG) {
define_label(output_ins.label,
output_ins.oprs[0].segment,
output_ins.oprs[0].offset, false);
@ -1611,14 +1616,35 @@ static void assemble_file(const char *fname, StrList **depend_ptr)
nasm_free(line);
} /* end while (line = preproc->getline... */
if (pass0 == 2 && global_offset_changed && !terminate_after_phase)
nasm_error(ERR_NONFATAL,
"phase error detected at end of assembly.");
if (global_offset_changed && !terminate_after_phase) {
switch (pass0) {
case 1:
nasm_error(ERR_WARNING|ERR_WARN_PHASE,
"phase error during stabilization pass, hoping for the best");
break;
case 2:
nasm_error(ERR_NONFATAL,
"phase error during code generation pass");
break;
default:
/* This is normal, we'll keep going... */
break;
}
}
if (pass1 == 1)
preproc->cleanup(1);
if ((passn > 1 && !global_offset_changed) || pass0 == 2) {
/*
* Always run at least two optimization passes (pass0 == 0);
* things like subsections will fail miserably without that.
* Once we commit to a stabilization pass (pass0 == 1), we can't
* go back, and if something goes bad, we can only hope
* that we don't end up with a phase error at the end.
*/
if ((passn > 1 && !global_offset_changed) || pass0 > 0) {
pass0++;
} else if (global_offset_changed &&
global_offset_changed < prev_offset_changed) {
@ -1941,14 +1967,16 @@ static void help(const char xopt)
" -w-foo disable warning foo (equiv. -Wno-foo)\n"
" -w[+-]error[=foo]\n"
" promote [specific] warnings to errors\n"
" -h show invocation summary and exit\n\n"
" -h show invocation summary and exit (also --help)\n\n"
" --pragma str pre-executes a specific %%pragma\n"
" --before str add line (usually a preprocessor statement) before the input\n"
" --prefix str prepend the given string to all the given string\n"
" to all extern, common and global symbols\n"
" --suffix str append the given string to all the given string\n"
" to all extern, common and global symbols\n"
" to all extern, common and global symbols (also --gprefix)\n"
" --postfix str append the given string to all the given string\n"
" to all extern, common and global symbols (also --gpostfix)\n"
" --lprefix str prepend the given string to all other symbols\n"
" --lpostfix str append the given string to all other symbols\n"
" --keep-all output files will not be removed even if an error happens\n"
" --limit-X val set execution limit X\n");
for (i = 0; i <= LIMIT_MAX; i++) {

View File

@ -486,7 +486,8 @@ restart_parse:
* Generally fix things. I think this is right as it is, but
* am still not certain.
*/
define_label(result->label, location.segment,
define_label(result->label,
in_absolute ? absolute.segment : location.segment,
location.offset, true);
}
}
@ -1027,7 +1028,7 @@ is_expression:
op->segment = NO_SEG; /* don't care again */
op->wrt = NO_SEG; /* still don't care */
if(optimizing >= 0 && !(op->type & STRICT)) {
if(optimizing.level >= 0 && !(op->type & STRICT)) {
/* Be optimistic */
op->type |=
UNITY | SBYTEWORD | SBYTEDWORD | UDWORD | SDWORD;
@ -1044,7 +1045,7 @@ is_expression:
if (is_simple(value)) {
if (n == 1)
op->type |= UNITY;
if (optimizing >= 0 && !(op->type & STRICT)) {
if (optimizing.level >= 0 && !(op->type & STRICT)) {
if ((uint32_t) (n + 128) <= 255)
op->type |= SBYTEDWORD;
if ((uint16_t) (n + 128) <= 255)
@ -1077,6 +1078,7 @@ is_expression:
}
} else { /* it's a register */
opflags_t rs;
uint64_t regset_size = 0;
if (value->type >= EXPR_SIMPLE || value->value != 1) {
nasm_error(ERR_NONFATAL, "invalid operand type");
@ -1084,13 +1086,32 @@ is_expression:
}
/*
* check that its only 1 register, not an expression...
* We do not allow any kind of expression, except for
* reg+value in which case it is a register set.
*/
for (i = 1; value[i].type; i++)
if (value[i].value) {
for (i = 1; value[i].type; i++) {
if (!value[i].value)
continue;
switch (value[i].type) {
case EXPR_SIMPLE:
if (!regset_size) {
regset_size = value[i].value + 1;
break;
}
/* fallthrough */
default:
nasm_error(ERR_NONFATAL, "invalid operand type");
goto fail;
}
}
if ((regset_size & (regset_size - 1)) ||
regset_size >= (UINT64_C(1) << REGSET_BITS)) {
nasm_error(ERR_NONFATAL | ERR_PASS2,
"invalid register set size");
regset_size = 0;
}
/* clear overrides, except TO which applies to FPU regs */
if (op->type & ~TO) {
@ -1099,12 +1120,31 @@ is_expression:
* is different from the register size
*/
rs = op->type & SIZE_MASK;
} else
} else {
rs = 0;
}
/*
* Make sure we're not out of nasm_reg_flags, still
* probably this should be fixed when we're defining
* the label.
*
* An easy trigger is
*
* e equ 0x80000000:0
* pshufw word e-0
*
*/
if (value->type < EXPR_REG_START ||
value->type > EXPR_REG_END) {
nasm_error(ERR_NONFATAL, "invalid operand type");
goto fail;
}
op->type &= TO;
op->type |= REGISTER;
op->type |= nasm_reg_flags[value->type];
op->type |= (regset_size >> 1) << REGSET_SHIFT;
op->decoflags |= brace_flags;
op->basereg = value->type;

View File

@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
* Copyright 1996-2017 The NASM Authors - All Rights Reserved
* Copyright 1996-2018 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@ -49,7 +49,7 @@
#include "assemble.h"
#include "error.h"
static enum directive_result asm_pragma(const struct pragma *pragma);
static enum directive_result output_pragma(const struct pragma *pragma);
static enum directive_result limit_pragma(const struct pragma *pragma);
/*
@ -87,14 +87,14 @@ static enum directive_result limit_pragma(const struct pragma *pragma);
*/
static struct pragma_facility global_pragmas[] =
{
{ "asm", asm_pragma },
{ "asm", NULL },
{ "limit", limit_pragma },
{ "list", NULL },
{ "file", NULL },
{ "input", NULL },
/* None of these should actually happen... */
{ "preproc", NULL }, /* This shouldn't happen... */
/* None of these should actually happen due to special handling */
{ "preproc", NULL }, /* Handled in the preprocessor by necessity */
{ "output", NULL },
{ "debug", NULL },
{ "ignore", NULL },
@ -110,6 +110,7 @@ static struct pragma_facility global_pragmas[] =
*/
static bool search_pragma_list(const struct pragma_facility *list,
const char *default_name,
pragma_handler generic_handler,
struct pragma *pragma)
{
const struct pragma_facility *pf;
@ -137,6 +138,10 @@ found_it:
else
rv = DIRR_UNKNOWN;
/* Is there an additional, applicable generic handler? */
if (rv == DIRR_UNKNOWN && generic_handler)
rv = generic_handler(pragma);
switch (rv) {
case DIRR_UNKNOWN:
switch (pragma->opcode) {
@ -210,15 +215,16 @@ void process_pragma(char *str)
pragma.tail = nasm_trim_spaces(p);
/* Look for a global pragma namespace */
if (search_pragma_list(global_pragmas, NULL, &pragma))
if (search_pragma_list(global_pragmas, NULL, NULL, &pragma))
return;
/* Look to see if it is an output backend pragma */
if (search_pragma_list(ofmt->pragmas, ofmt->shortname, &pragma))
if (search_pragma_list(ofmt->pragmas, ofmt->shortname,
output_pragma, &pragma))
return;
/* Look to see if it is a debug format pragma */
if (search_pragma_list(dfmt->pragmas, dfmt->shortname, &pragma))
if (search_pragma_list(dfmt->pragmas, dfmt->shortname, NULL, &pragma))
return;
/*
@ -234,9 +240,10 @@ void process_pragma(char *str)
}
/*
* Pragmas for the assembler proper
* Generic pragmas that apply to all output backends; these are handled
* specially so they can be made selective based on the output format.
*/
static enum directive_result asm_pragma(const struct pragma *pragma)
static enum directive_result output_pragma(const struct pragma *pragma)
{
switch (pragma->opcode) {
case D_PREFIX:
@ -258,6 +265,9 @@ static enum directive_result asm_pragma(const struct pragma *pragma)
}
}
/*
* %pragma limit to set resource limits
*/
static enum directive_result limit_pragma(const struct pragma *pragma)
{
return nasm_set_limit(pragma->opname, pragma->tail);

View File

@ -2210,8 +2210,7 @@ static int parse_size(const char *str) {
{ "byte", "dword", "oword", "qword", "tword", "word", "yword" };
static const int sizes[] =
{ 0, 1, 4, 16, 8, 10, 2, 32 };
return sizes[bsii(str, size_names, ARRAY_SIZE(size_names))+1];
return str ? sizes[bsii(str, size_names, ARRAY_SIZE(size_names))+1] : 0;
}
/*
@ -3948,6 +3947,8 @@ static Token *expand_mmac_params_range(MMacro *mac, Token *tline, Token ***last)
* only first token will be passed.
*/
tm = mac->params[(fst + mac->rotate) % mac->nparam];
if (!tm)
goto err;
head = new_Token(NULL, tm->type, tm->text, 0);
tt = &head->next, tm = tm->next;
while (tok_isnt_(tm, ",")) {
@ -4472,7 +4473,9 @@ again:
}
if (tline->type == TOK_SMAC_END) {
tline->a.mac->in_progress = false;
/* On error path it might already be dropped */
if (tline->a.mac)
tline->a.mac->in_progress = false;
tline = delete_Token(tline);
} else {
t = *tail = tline;

View File

@ -49,6 +49,15 @@
#include "regdis.h"
#include "disp8.h"
#define fetch_safe(_start, _ptr, _size, _need, _op) \
do { \
if (((_ptr) - (_start)) >= ((_size) - (_need))) \
_op; \
} while (0)
#define fetch_or_return(_start, _ptr, _size, _need) \
fetch_safe(_start, _ptr, _size, _need, return 0)
/*
* Flags that go into the `segment' field of `insn' structures
* during disassembly.
@ -1108,8 +1117,8 @@ static const char * const condition_name[16] = {
"s", "ns", "pe", "po", "l", "nl", "ng", "g"
};
int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
int64_t offset, int autosync, iflag_t *prefer)
int32_t disasm(uint8_t *data, int32_t data_size, char *output, int outbufsize, int segsize,
int64_t offset, int autosync, iflag_t *prefer)
{
const struct itemplate * const *p, * const *best_p;
const struct disasm_index *ix;
@ -1144,41 +1153,52 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
switch (*data) {
case 0xF2:
case 0xF3:
fetch_or_return(origdata, data, data_size, 1);
prefix.rep = *data++;
break;
case 0x9B:
fetch_or_return(origdata, data, data_size, 1);
prefix.wait = *data++;
break;
case 0xF0:
fetch_or_return(origdata, data, data_size, 1);
prefix.lock = *data++;
break;
case 0x2E:
fetch_or_return(origdata, data, data_size, 1);
segover = "cs", prefix.seg = *data++;
break;
case 0x36:
fetch_or_return(origdata, data, data_size, 1);
segover = "ss", prefix.seg = *data++;
break;
case 0x3E:
fetch_or_return(origdata, data, data_size, 1);
segover = "ds", prefix.seg = *data++;
break;
case 0x26:
fetch_or_return(origdata, data, data_size, 1);
segover = "es", prefix.seg = *data++;
break;
case 0x64:
fetch_or_return(origdata, data, data_size, 1);
segover = "fs", prefix.seg = *data++;
break;
case 0x65:
fetch_or_return(origdata, data, data_size, 1);
segover = "gs", prefix.seg = *data++;
break;
case 0x66:
fetch_or_return(origdata, data, data_size, 1);
prefix.osize = (segsize == 16) ? 32 : 16;
prefix.osp = *data++;
break;
case 0x67:
fetch_or_return(origdata, data, data_size, 1);
prefix.asize = (segsize == 32) ? 16 : 32;
prefix.asp = *data++;
break;
@ -1186,6 +1206,7 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
case 0xC4:
case 0xC5:
if (segsize == 64 || (data[1] & 0xc0) == 0xc0) {
fetch_or_return(origdata, data, data_size, 2);
prefix.vex[0] = *data++;
prefix.vex[1] = *data++;
@ -1193,6 +1214,7 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
prefix.vex_c = RV_VEX;
if (prefix.vex[0] == 0xc4) {
fetch_or_return(origdata, data, data_size, 1);
prefix.vex[2] = *data++;
prefix.rex |= (~prefix.vex[1] >> 5) & 7; /* REX_RXB */
prefix.rex |= (prefix.vex[2] >> (7-3)) & REX_W;
@ -1214,6 +1236,7 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
case 0x62:
{
if (segsize == 64 || ((data[1] & 0xc0) == 0xc0)) {
fetch_or_return(origdata, data, data_size, 4);
data++; /* 62h EVEX prefix */
prefix.evex[0] = *data++;
prefix.evex[1] = *data++;
@ -1237,6 +1260,7 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
case 0x8F:
if ((data[1] & 030) != 0 &&
(segsize == 64 || (data[1] & 0xc0) == 0xc0)) {
fetch_or_return(origdata, data, data_size, 3);
prefix.vex[0] = *data++;
prefix.vex[1] = *data++;
prefix.vex[2] = *data++;
@ -1272,6 +1296,7 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
case REX_P + 0xE:
case REX_P + 0xF:
if (segsize == 64) {
fetch_or_return(origdata, data, data_size, 1);
prefix.rex = *data++;
if (prefix.rex & REX_W)
prefix.osize = 64;
@ -1293,8 +1318,10 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
return 0; /* No instruction table at all... */
dp = data;
fetch_or_return(origdata, dp, data_size, 1);
ix += *dp++;
while (ix->n == -1) {
fetch_or_return(origdata, dp, data_size, 1);
ix = (const struct disasm_index *)ix->p + *dp++;
}
@ -1431,6 +1458,9 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
slen += snprintf(output + slen, outbufsize - slen, "to ");
slen += snprintf(output + slen, outbufsize - slen, "%s",
nasm_reg_names[reg-EXPR_REG_START]);
if (t & REGSET_MASK)
slen += snprintf(output + slen, outbufsize - slen, "+%d",
(int)((t & REGSET_MASK) >> (REGSET_SHIFT-1))-1);
if (is_evex && deco)
slen += append_evex_reg_deco(output + slen, outbufsize - slen,
deco, ins.evex_p);

View File

@ -42,8 +42,8 @@
#define INSN_MAX 32 /* one instruction can't be longer than this */
int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
int64_t offset, int autosync, iflag_t *prefer);
int32_t disasm(uint8_t *data, int32_t data_size, char *output, int outbufsize, int segsize,
int64_t offset, int autosync, iflag_t *prefer);
int32_t eatbyte(uint8_t *data, char *output, int outbufsize, int segsize);
#endif

View File

@ -316,9 +316,8 @@ int main(int argc, char **argv)
nextsync = next_sync(offset, &synclen);
}
while (p > q && (p - q >= INSN_MAX || lenread == 0)) {
lendis =
disasm((uint8_t *) q, outbuf, sizeof(outbuf), bits,
offset, autosync, &prefer);
lendis = disasm((uint8_t *)q, INSN_MAX, outbuf, sizeof(outbuf),
bits, offset, autosync, &prefer);
if (!lendis || lendis > (p - q)
|| ((nextsync || synclen) &&
(uint32_t)lendis > nextsync - offset))

View File

@ -7,7 +7,70 @@
The NASM 2 series supports x86-64, and is the production version of NASM
since 2007.
\S{cl-2.13.04} Version 2.13.04
\S{cl-2.14} Version 2.14
\b Fixed null dereference in corrupted invalid single line macros.
\b Fixed division by zero which may happen if source code is malformed.
\b Fixed out of bound access in processing of malformed segment override.
\b Fixed out of bound access in certain \c{EQU} parsing.
\b Fixed buffer underflow in float parsing.
\b Added \c{SGX} (Intel Software Guard Extensions) instructions.
\b Added \c{+n} syntax for multiple contiguous registers.
\b Fixed \c{subsections_via_symbols} for \c{macho} object format.
\b Added the \c{--gprefix}, \c{--gpostfix}, \c{--lprefix}, and
\c{--lpostfix} command line options, to allow command line base symbol
renaming. See \k{opt-pfix}.
\b Allow label renaming to be specified by \c{%pragma} in addition to
from the command line. See \k{mangling}.
\b Supported generic \c{%pragma} namespaces, \c{output} and \c{debug}. See
\k{gen-namespace}.
\b Added the \c{--pragma} command line option to inject a \c{%pragma}
directive. See \k{opt-pragma}.
\b Added the \c{--before} command line option to accept preprocess
statement before input. See \k{opt-before}.
\b Added \c{AVX512} \c{VBMI2} (Additional Bit Manipulation), \c{VNNI} (Vector
Neural Network), \c{BITALG} (Bit Algorithm), and \c{GFNI} (Galois Field New
Instruction) instructions.
\b Added the \c{STATIC} directive for local symbols that should be
renamed using global-symbol rules. See \k{static}.
\b Allow a symbol to be defined as \c{EXTERN} and then later
overridden as \c{GLOBAL} or \c{COMMON}. Furthermore, a symbol declared
\c{EXTERN} and then defined will be treated as \c{GLOBAL}. See \k{extern}.
\b The \c{GLOBAL} directive no longer is required to precede the
definition of the symbol.
\b Support \c{private_extern} as \c{macho} specific extension to the
\c{GLOBAL} directive. See \k{macho-pext}.
\b Updated \c{UD0} encoding to match with the specification
\b Added the \c{--limit-X} command line option to set execution
limits. See \k{opt-limit}.
\b Updated the \c{Codeview} version number to be aligned with \c{MASM}.
\b Added the \c{--keep-all} command line option to preserve output
files. See \k{opt-keep-all}.
\b Added the \c{--include} command line option, an alias to \c{-P} (\k{opt-p}).
\b Added the \c{--help} command line option as an alias to \c{-h} (\k{syntax}).
\b Added \c{-W}, \c{-D}, and \c{-Q} suffix aliases for \c{RET}
instructions so the operand sizes of these instructions can be

View File

@ -368,6 +368,8 @@ To get further usage instructions from NASM, try typing
\c nasm -h
\c{--help} option is also the same.
As \c{-hf}, this will also list the available output file formats, and what they
are.
@ -657,10 +659,13 @@ option. So running
is equivalent to running \c{nasm myfile.asm} and placing the
directive \c{%include "myinc.inc"} at the start of the file.
\c{--include} option is also accepted.
For consistency with the \c{-I}, \c{-D} and \c{-U} options, this
option can also be specified as \c{-P}.
\S{opt-d} The \i\c{-d}\I\c{-D} Option: \I{pre-defining macros}Pre-Define a Macro
\I\c{%define}Just as the \c{-p} option gives an alternative to placing
@ -917,13 +922,72 @@ is indicated by an asterisk. For example:
\c dwarf elf32 (i386) dwarf debug format for Linux
\S{opt-pfix} The \i\c{--prefix} and \i\c{--postfix} Options.
\S{opt-pfix} The \i\c{--(g|l)prefix}, \i\c{--(g|l)postfix} Options.
The \c{--prefix} and \c{--postfix} options prepend or append
(respectively) the given argument to all \c{global} or
\c{extern} variables. E.g. \c{--prefix _} will prepend the
underscore to all global and external variables, as C requires it in
some, but not all, system calling conventions.
The \c{--(g)prefix} options prepend the given argument
to all \c{extern}, \c{common}, \c{static}, and \c{global} symbols, and the
\c{--lprefix} option prepends to all other symbols. Similarly,
\c{--(g)postfix} and \c{--lpostfix} options append
the argument in the exactly same way as the \c{--xxprefix} options does.
Running this:
\c nasm -f macho --gprefix _
is equivalent to place the directive with \c{%pragma macho gprefix _}
at the start of the file (\k{mangling}). It will prepend the underscore
to all global and external variables, as C requires it in some, but not all,
system calling conventions.
\S{opt-pragma} The \i\c{--pragma} Option
NASM accepts an argument as \c{%pragma} option, which is like placing
a \c{%pragma} preprocess statement at the beginning of the source.
Running this:
\c nasm -f macho --pragma "macho gprefix _"
is equivalent to the example in \k{opt-pfix}.
\S{opt-before} The \i\c{--before} Option
A preprocess statement can be accepted with this option. The example
shown in \k{opt-pragma} is the same as running this:
\c nasm -f macho --before "%pragma macho gprefix _"
\S{opt-limit} The \i\c{--limit-X} Option
This option allows user to setup various maximum values for these:
\b\c{--limit-passes}: Number of maximum allowed passes. Default is
effectively unlimited.
\b\c{--limit-stalled-passes}: Maximum number of allowed unfinished
passes. Default is 1000.
\b\c{--limit-macro-levels}: Define maximum depth of macro expansion
(in preprocess). Default is 1000000.
\b\c{--limit-rep}: Maximum number of allowed preprocessor loop, defined
under \c{%rep}. Default is 1000000.
\b\c{--limit-eval}: This number sets the boundary condition of allowed
expression length. Default is 1000000.
\b\c{--limit-lines}: Total number of source lines as allowed to be
processed. Default is 2000000000.
In example, running this limits the maximum line count to be 1000.
\c nasm --limit-lines 1000
\S{opt-keep-all} The \i\c{--keep-all} Option
This option doesn't delete any output files even if an error happens.
\S{nasmenv} The \i\c{NASMENV} \i{Environment} Variable
@ -4540,8 +4604,12 @@ only in that it can take only one argument at a time: the support
for multiple arguments is implemented at the preprocessor level.
You can declare the same variable as \c{EXTERN} more than once: NASM
will quietly ignore the second and later redeclarations. You can't
declare a variable as \c{EXTERN} as well as something else, though.
will quietly ignore the second and later redeclarations.
If a variable is declared both \c{GLOBAL} and \c{EXTERN}, or if it is
declared as \c{EXTERN} and then defined, it will be treated as
\c{GLOBAL}. If a variable is declared both as \c{COMMON} and
\c{EXTERN}, it will be treated as \c{COMMON}.
\H{global} \i\c{GLOBAL}: \i{Exporting Symbols} to Other Modules
@ -4552,9 +4620,6 @@ linker errors, some other module must actually \e{define} the
symbol and declare it as \c{GLOBAL}. Some assemblers use the name
\i\c{PUBLIC} for this purpose.
The \c{GLOBAL} directive applying to a symbol must appear \e{before}
the definition of the symbol.
\c{GLOBAL} uses the same syntax as \c{EXTERN}, except that it must
refer to symbols which \e{are} defined in the same module as the
\c{GLOBAL} directive. For example:
@ -4607,6 +4672,61 @@ Once again, like \c{EXTERN} and \c{GLOBAL}, the primitive form of
\c{COMMON} differs from the user-level form only in that it can take
only one argument at a time.
\H{static} \i\c{STATIC}: Local Symbols within Modules
Opposite to \c{EXTERN} and \c{GLOBAL}, \c{STATIC} is local symbol, but
should be named according to the global mangling rules (named by
analogy with the C keyword \c{static} as applied to functions or
global variables).
\c static foo
\c foo:
\c ; codes
Unlike \c{GLOBAL}, \c{STATIC} does not allow object formats to accept
private extensions mentioned in \k{global}.
\H{mangling} \i\c{(G|L)PREFIX}, \i\c{(G|L)POSTFIX}: Mangling Symbols
\c{PREFIX}, \c{GPREFIX}, \c{LPREFIX}, \c{POSTFIX}, \c{GPOSTFIX}, and
\c{LPOSTFIX} directives can prepend or append the given argument to
a certain type of symbols. The directive should be as a preprocess
statement. Each usage is:
\b\c{PREFIX}|\c{GPREFIX}: Prepend the argument to all \c{EXTERN}
\c{COMMON}, \c{STATIC}, and \c{GLOBAL} symbols
\b\c{LPREFIX}: Prepend the argument to all other symbols
such as Local Labels, and backend defined symbols
\b\c{POSTFIX}|\c{GPOSTFIX}: Append the argument to all \c{EXTERN}
\c{COMMON}, \c{STATIC}, and \c{GLOBAL} symbols
\b\c{LPOSTFIX}: Append the argument to all other symbols
such as Local Labels, and backend defined symbols
This is a macro implemented as a \c{%pragma}:
\c %pragma macho lprefix L_
Commandline option is also possible. See also \k{opt-pfix}.
\H{gen-namespace} \i\c{OUTPUT}, \i\c{DEBUG}: Generic Namespaces
\c{OUTPUT} and \c{DEBUG} are generic \c{%pragma} namespaces that are
supposed to redirect to the current output and debug formats.
For example, when mangling local symbols via the generic namespace:
\c %pragma output gprefix _
This is useful when the directive is needed to be output format
agnostic.
The example is also euquivalent to this, when the output format is \c{elf}:
\c %pragma elf gprefix _
\H{CPU} \i\c{CPU}: Defining CPU Dependencies
@ -5658,7 +5778,7 @@ comma. The following flags can also be specified:
\b \c{data} - this section contains initialized data items
\b \c{text} - this section contains code exclusively
\b \c{code} - this section contains code exclusively
\b \c{mixed} - this section contains both code and data
@ -5731,6 +5851,19 @@ non-Mach-O builds of the same source code:
\c %pragma macho no_dead_strip symbol...
\S{macho-pext} \c{macho} specific extensions to the \c{GLOBAL}
Directive: \i\c{private_extern}
The directive extension to \c{GLOBAL} marks the symbol with limited
global scope. For example, you can specify the global symbol with
this extension:
\c global foo:private_extern
\c foo:
\c ; codes
Using with static linker will clear the private extern attribute.
But linker option like \c{-keep_private_externs} can avoid it.
\H{elffmt} \i\c{elf32}, \i\c{elf64}, \i\c{elfx32}: \I{ELF}\I{linux, elf}\i{Executable and Linkable
Format} Object Files

View File

@ -6,7 +6,8 @@
GLOBAL variables:
optimizing -1 flags nasm 0.98 compatible operation;
optimizing optimization meta data (with level and flag info)
.level -1 flags nasm 0.98 compatible operation;
offsets usually are explicit (short/near)
no optimization passes
0 flags non-optimized assembly; forward
@ -17,7 +18,8 @@ GLOBAL variables:
the actual recommended minimum setting
optimization passes (2 or more, plus
passes 1 and 2 will be required)
.flag 0 allow all optimizations
1 disallow jump match optimization
pass0 0 flags an optimizer pass (multiple passes)
1 flags pass1 (define labels)

View File

@ -23,6 +23,9 @@ while ($ARGV[0] =~ /^-(.*)$/) {
}
}
# Ghostscript executable name. "gs" on Unix-based systems.
my $gs = 'gs';
my ($in, $out) = @ARGV;
if (!defined($out)) {
@ -70,6 +73,17 @@ sub win32_gs_help() {
$ENV{'PATH'} .= ';' . $gs[0]->{'/GS_LIB'};
$ENV{'GS_FONTPATH'} .= (defined($ENV{'GS_FONTPATH'}) ? ';' : '')
. $ENV{'windir'}.'\\fonts';
my $gsp = undef;
foreach my $p (split(/\;/, $gs[0]->{'/GS_LIB'})) {
foreach my $exe ('gswin64c.exe', 'gswin32c.exe', 'gs.exe') {
last if (defined($gsp));
my $e = File::Spec->catpath($p, $exe);
$gsp = $e if (-f $e && -x _);
}
}
$gs = $gsp if (defined($gsp));
}
# Remove output file
@ -80,13 +94,19 @@ my $r = system('acrodist', '-n', '-q', '--nosecurity', '-o', $out, $in);
exit 0 if ( !$r && -f $out );
# 2. ps2pdf (from Ghostscript)
# The -I clause helps Ghostscript pick up the Fontdir file written by findfont.ph
# GhostScript uses # rather than - to separate options and values on Windows, it seems...
#
# GhostScript uses # rather than = to separate options and values on Windows,
# it seems. Call gs directly rather than ps2pdf, because -dSAFER
# breaks font discovery on some systems, apparently.
win32_gs_help();
my $o = $win32_ok ? '#' : '-';
my $r = system('ps2pdf', "-dOptimize${o}true", "-dEmbedAllFonts${o}true",
my $o = $win32_ok ? '#' : '=';
my $r = system($gs, "-dCompatibilityLevel${o}1.4", "-q",
"-P-", "-dNOPAUSE", "-dBATCH", "-sDEVICE${o}pdfwrite",
"-sstdout${o}%stderr", "-sOutputFile${o}${out}",
"-dOptimize${o}true", "-dEmbedAllFonts${o}true",
"-dCompressPages${o}" . ($compress ? 'true' : 'false'),
"-dUseFlateCompression${o}true", $in, $out);
"-dUseFlateCompression${o}true",
"-c", ".setpdfwrite", "-f", $in);
exit 0 if ( !$r && -f $out );
# 3. pstopdf (BSD/MacOS X utility)

View File

@ -1,7 +1,7 @@
#!/usr/bin/perl
## --------------------------------------------------------------------------
##
## Copyright 1996-2017 The NASM Authors - All Rights Reserved
## Copyright 1996-2018 The NASM Authors - All Rights Reserved
## See the file AUTHORS included with the NASM distribution for
## the specific copyright holders.
##
@ -325,7 +325,7 @@ sub got_para {
$snum = 0;
$xref = "section-$cnum.$hnum";
$pflags = "head $cnum.$hnum :$xref";
die "badly formatted heading: $_\n" if !/^\\[HP]{([^\}]*)}\s*(.*)$/;
die "badly formatted heading: $_\n" if !/^\\[HP]\{([^\}]*)\}\s*(.*)$/;
$refs{$1} = "section $cnum.$hnum";
$node = "Section $cnum.$hnum";
&add_item($node, 2);

View File

@ -115,9 +115,10 @@ static inline vefunc nasm_set_verror(vefunc ve)
#define ERR_WARN_NOTMY_PRAGMA WARN(19) /* pragma inapplicable */
#define ERR_WARN_UNK_WARNING WARN(20) /* unknown warning */
#define ERR_WARN_NEG_REP WARN(21) /* negative repeat count */
#define ERR_WARN_PHASE WARN(22) /* phase error in pass 1 */
/* The "all" warning acts as a global switch, it must come last */
#define ERR_WARN_ALL 22 /* Do not use WARN() here */
#define ERR_WARN_ALL 23 /* Do not use WARN() here */
struct warning {
const char *name;

View File

@ -728,10 +728,11 @@ enum directive_result {
* as part of the struct pragma.
*/
struct pragma;
typedef enum directive_result (*pragma_handler)(const struct pragma *);
struct pragma_facility {
const char *name;
enum directive_result (*handler)(const struct pragma *);
pragma_handler handler;
};
/*
@ -911,9 +912,14 @@ struct ofmt {
* The offset isn't passed; and may not be stable at this point.
* The subsection number is a field available for use by the
* backend. It is initialized to NO_SEG.
*
* If "copyoffset" is set by the backend then the offset is
* copied from the previous segment, otherwise the new segment
* is treated as a new segment the normal way.
*/
int32_t (*herelabel)(const char *name, enum label_type type,
int32_t seg, int32_t *subsection);
int32_t seg, int32_t *subsection,
bool *copyoffset);
/*
* This procedure is called to modify section alignment,
@ -1243,11 +1249,25 @@ enum decorator_tokens {
* 2 = pass 2
*/
/*
* flag to disable optimizations selectively
* this is useful to turn-off certain optimizations
*/
enum optimization_disable_flag {
OPTIM_ALL_ENABLED = 0,
OPTIM_DISABLE_JMP_MATCH = 1
};
struct optimization {
int level;
int flag;
};
extern int pass0;
extern int64_t passn; /* Actual pass number */
extern bool tasm_compatible_mode;
extern int optimizing;
extern struct optimization optimizing;
extern int globalbits; /* 16, 32 or 64-bit mode */
extern int globalrel; /* default to relative addressing? */
extern int globalbnd; /* default to using bnd prefix? */

View File

@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
* Copyright 1996-2013 The NASM Authors - All Rights Reserved
* Copyright 1996-2018 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@ -40,6 +40,7 @@
#include "compiler.h"
#include "tables.h" /* for opflags_t and nasm_reg_flags[] */
#include "regs.h"
/*
* Here we define the operand types. These are implemented as bit
@ -117,6 +118,16 @@
#define SIZE_MASK OP_GENMASK(SIZE_BITS, SIZE_SHIFT)
#define GEN_SIZE(bit) OP_GENBIT(bit, SIZE_SHIFT)
/*
* Register set count
*
* Bits: 47 - 43
*/
#define REGSET_SHIFT (43)
#define REGSET_BITS (5)
#define REGSET_MASK OP_GENMASK(REGSET_BITS, REGSET_SHIFT)
#define GEN_REGSET(bit) OP_GENBIT(bit, REGSET_SHIFT)
/*
* Bits distribution (counted from 0)
*
@ -131,6 +142,7 @@
* .......................................11111111................. subclasses
* ................................1111111......................... specials
* .....................11111111111................................ sizes
* ................11111........................................... regset count
*/
#define REGISTER GEN_OPTYPE(0) /* register number in 'basereg' */
@ -165,8 +177,17 @@
#define REG_CLASS_OPMASK GEN_REG_CLASS(8)
#define REG_CLASS_BND GEN_REG_CLASS(9)
#define is_class(class, op) (!((opflags_t)(class) & ~(opflags_t)(op)))
#define is_reg_class(class, reg) is_class((class), nasm_reg_flags[(reg)])
static inline bool is_class(opflags_t class, opflags_t op)
{
return !(class & ~op);
}
static inline bool is_reg_class(opflags_t class, opflags_t reg)
{
if (reg >= EXPR_REG_START && reg <= EXPR_REG_END)
return is_class(class, nasm_reg_flags[reg]);
return false;
}
#define IS_SREG(reg) is_reg_class(REG_SREG, (reg))
#define IS_FSGS(reg) is_reg_class(REG_FSGS, (reg))
@ -268,4 +289,11 @@
#define ZMM0 (GEN_SUBCLASS(1) | GEN_SUBCLASS(6) | ZMMREG) /* ZMM register zero */
#define ZMM_L16 ( GEN_SUBCLASS(6) | ZMMREG) /* ZMM register 0 ~ 15 */
/* Register set sizes */
#define RS2 GEN_REGSET(0)
#define RS4 GEN_REGSET(1)
#define RS8 GEN_REGSET(2)
#define RS16 GEN_REGSET(3)
#define RS32 GEN_REGSET(4)
#endif /* NASM_OPFLAGS_H */

View File

@ -137,14 +137,17 @@ static int32_t dbg_section_names(char *name, int pass, int *bits)
}
static int32_t dbg_herelabel(const char *name, enum label_type type,
int32_t oldseg, int32_t *subsection)
int32_t oldseg, int32_t *subsection,
bool *copyoffset)
{
int32_t newseg = oldseg;
if (subsections_via_symbols && type != LBL_LOCAL) {
newseg = *subsection;
if (newseg == NO_SEG)
if (newseg == NO_SEG) {
newseg = *subsection = seg_alloc();
*copyoffset = true; /* Minic MachO for now */
}
}
fprintf(ofile, "herelabel %s type %d (seg %08x) -> %08x\n",
name, type, oldseg, newseg);

View File

@ -363,7 +363,7 @@ static struct section *get_section_by_index(int32_t index)
if (index < 0 || index >= SEG_ABS || (index & 1))
return NULL;
return (struct section *)raa_read(section_by_index, index >> 1);
return raa_read_ptr(section_by_index, index >> 1);
}
struct dir_list {
@ -495,7 +495,7 @@ static int64_t add_reloc(struct section *sect, int32_t section,
r = nasm_malloc(sizeof(struct reloc));
r->addr = sect->size & ~R_SCATTERED;
r->ext = 1;
adjust = bytes;
adjust = 0;
/* match byte count 1, 2, 4, 8 to length codes 0, 1, 2, 3 respectively */
r->length = ilog2_32(bytes);
@ -514,7 +514,6 @@ static int64_t add_reloc(struct section *sect, int32_t section,
if (section == NO_SEG) {
/* absolute (can this even happen?) */
r->ext = 0;
r->snum = NO_SECT;
} else if (fi == NO_SECT) {
/* external */
r->snum = raa_read(extsyms, section);
@ -522,7 +521,6 @@ static int64_t add_reloc(struct section *sect, int32_t section,
/* local */
r->ext = 0;
r->snum = fi;
adjust = -sect->size;
}
break;
@ -531,40 +529,27 @@ static int64_t add_reloc(struct section *sect, int32_t section,
r->type = fmt.reloc_rel;
r->pcrel = 1;
if (section == NO_SEG) {
/* absolute - seems to produce garbage no matter what */
nasm_error(ERR_NONFATAL, "Mach-O does not support relative "
"references to absolute addresses");
goto bail;
#if 0
/* This "seems" to be how it ought to work... */
struct symbol *sym = macho_find_sym(&absolute_sect, offset,
false, false);
if (!sym)
goto bail;
sect->extreloc = 1;
r->snum = NO_SECT;
adjust = -sect->size;
#endif
/* may optionally be converted below by fmt.forcesym */
r->ext = 0;
} else if (fi == NO_SECT) {
/* external */
sect->extreloc = 1;
r->snum = raa_read(extsyms, section);
if (reltype == RL_BRANCH)
r->type = X86_64_RELOC_BRANCH;
else if (r->type == GENERIC_RELOC_VANILLA)
adjust = -sect->size;
} else {
/* local */
r->ext = 0;
r->snum = fi;
adjust = -sect->size;
if (reltype == RL_BRANCH)
r->type = X86_64_RELOC_BRANCH;
}
break;
case RL_SUB:
r->pcrel = 0;
case RL_SUB: /* obsolete */
nasm_error(ERR_WARNING, "relcation with subtraction"
"becomes to be obsolete");
r->ext = 0;
r->type = X86_64_RELOC_SUBTRACTOR;
break;
@ -581,34 +566,46 @@ static int64_t add_reloc(struct section *sect, int32_t section,
goto needsym;
needsym:
r->pcrel = 1;
r->pcrel = (fmt.ptrsize == 8 ? 1 : 0);
if (section == NO_SEG) {
nasm_error(ERR_NONFATAL, "Unsupported use of use of WRT");
goto bail;
} else if (fi == NO_SECT) {
/* external */
r->snum = raa_read(extsyms, section);
} else {
/* internal - does it really need to be global? */
struct symbol *sym = macho_find_sym(s, offset, true,
reltype != RL_TLV);
if (!sym)
/* internal - GOTPCREL doesn't need to be in global */
struct symbol *sym = macho_find_sym(s, offset,
false, /* reltype != RL_TLV */
true);
if (!sym) {
nasm_error(ERR_NONFATAL, "Symbol for WRT not found");
goto bail;
}
adjust -= sym->symv[0].key;
r->snum = sym->initial_snum;
}
break;
}
/* For 64-bit Mach-O, force a symbol reference if at all possible */
if (!r->ext && r->snum != NO_SECT && fmt.forcesym) {
struct symbol *sym = macho_find_sym(s, offset, false, false);
/*
* For 64-bit Mach-O, force a symbol reference if at all possible
* Allow for r->snum == R_ABS by searching absolute_sect
*/
if (!r->ext && fmt.forcesym) {
struct symbol *sym = macho_find_sym(s ? s : &absolute_sect,
offset, false, false);
if (sym) {
adjust = bytes - sym->symv[0].key;
adjust -= sym->symv[0].key;
r->snum = sym->initial_snum;
r->ext = 1;
}
}
if (r->pcrel)
adjust += ((r->ext && fmt.ptrsize == 8) ? bytes : -(int64_t)sect->size);
/* NeXT as puts relocs in reversed order (address-wise) into the
** files, so we do the same, doesn't seem to make much of a
** difference either way */
@ -661,6 +658,9 @@ static void macho_output(int32_t secto, const void *data,
if (is_bss && type != OUT_RESERVE) {
nasm_error(ERR_WARNING, "attempt to initialize memory in "
"BSS section: ignored");
/* FIXME */
nasm_error(ERR_WARNING, "section size may be negative"
"with address symbols");
s->size += realsize(type, size);
return;
}
@ -698,8 +698,11 @@ static void macho_output(int32_t secto, const void *data,
"Mach-O 64-bit format does not support"
" 32-bit absolute addresses");
} else {
add_reloc(s, section, addr, RL_ABS, asize);
addr += add_reloc(s, section, addr, RL_ABS, asize);
}
} else if (wrt == macho_tlvp_sect && fmt.ptrsize != 8 &&
asize == (int) fmt.ptrsize) {
addr += add_reloc(s, section, addr, RL_TLV, asize);
} else {
nasm_error(ERR_NONFATAL, "Mach-O format does not support"
" this use of WRT");
@ -785,7 +788,7 @@ static void macho_output(int32_t secto, const void *data,
reltype = RL_GOTLOAD;
}
}
} else if (wrt == macho_tlvp_sect) {
} else if (wrt == macho_tlvp_sect && fmt.ptrsize == 8) {
reltype = RL_TLV;
} else {
nasm_error(ERR_NONFATAL, "Mach-O format does not support"
@ -1008,7 +1011,8 @@ static int32_t macho_section(char *name, int pass, int *bits)
}
static int32_t macho_herelabel(const char *name, enum label_type type,
int32_t section, int32_t *subsection)
int32_t section, int32_t *subsection,
bool *copyoffset)
{
struct section *s;
int32_t subsec;
@ -1033,6 +1037,7 @@ static int32_t macho_herelabel(const char *name, enum label_type type,
}
s->subsection = subsec;
*copyoffset = true; /* Maintain previous offset */
return subsec;
}
@ -1045,8 +1050,8 @@ static void macho_symdef(char *name, int32_t section, int64_t offset,
#if defined(DEBUG) && DEBUG>2
nasm_error(ERR_DEBUG,
" macho_symdef: %s, sec=%"PRIx32", off=%"PRIx64", is_global=%d, %s\n",
name, section, offset, is_global, special);
" macho_symdef: %s, pass0=%d, passn=%"PRId64", sec=%"PRIx32", off=%"PRIx64", is_global=%d, %s\n",
name, pass0, passn, section, offset, is_global, special);
#endif
if (is_global == 3) {
@ -1109,6 +1114,9 @@ static void macho_symdef(char *name, int32_t section, int64_t offset,
special_used = true;
}
/* track the initially allocated symbol number for use in future fix-ups */
sym->initial_snum = nsyms;
if (section == NO_SEG) {
/* symbols in no section get absolute */
sym->type |= N_ABS;
@ -1123,9 +1131,6 @@ static void macho_symdef(char *name, int32_t section, int64_t offset,
/* get the in-file index of the section the symbol was defined in */
sym->sect = s ? s->fileindex : NO_SECT;
/* track the initially allocated symbol number for use in future fix-ups */
sym->initial_snum = nsyms;
if (!s) {
/* remember symbol number of references to external
** symbols, this works because every external symbol gets
@ -1874,6 +1879,9 @@ macho_pragma(const struct pragma *pragma)
if (real)
head_flags |= MH_SUBSECTIONS_VIA_SYMBOLS;
/* Jmp-match optimization conflicts */
optimizing.flag |= OPTIM_DISABLE_JMP_MATCH;
return DIRR_OK;
case D_NO_DEAD_STRIP:

View File

@ -1380,9 +1380,10 @@ static int32_t obj_segment(char *name, int pass, int *bits)
attrs++;
}
obj_idx = 1;
for (seg = seghead; seg; seg = seg->next) {
obj_idx++;
for (seg = seghead, obj_idx = 1; ; seg = seg->next, obj_idx++) {
if (!seg)
break;
if (!strcmp(seg->name, name)) {
if (attrs > 0 && pass == 1)
nasm_error(ERR_WARNING, "segment attributes specified on"
@ -1403,7 +1404,7 @@ static int32_t obj_segment(char *name, int pass, int *bits)
seg->obj_index = obj_idx;
seg->grp = NULL;
any_segs = true;
seg->name = NULL;
seg->name = nasm_strdup(name);
seg->currentpos = 0;
seg->align = 1; /* default */
seg->use32 = false; /* default */

View File

@ -12,46 +12,46 @@ $(NASM):
$(MAKE) -C ..
%.bin: %.asm $(NASMDEP)
$(NASM) $(NASMOPT) -f bin -o $@ -MD $@.dep -l $*.lst $<
$(NASM) $(NASMOPT) -f bin -o $@ -MD $@.dep -l $@.lst $<
%.ith: %.asm $(NASMDEP)
$(NASM) $(NASMOPT) -f ith -o $@ -MD $@.dep -l $*.lst $<
$(NASM) $(NASMOPT) -f ith -o $@ -MD $@.dep -l $@.lst $<
%.srec: %.asm $(NASMDEP)
$(NASM) $(NASMOPT) -f srec -o $@ -MD $@.dep -l $*.lst $<
$(NASM) $(NASMOPT) -f srec -o $@ -MD $@.dep -l $@.lst $<
%.o: %.asm $(NASMDEP)
$(NASM) $(NASMOPT) -f elf32 -o $@ -MD $@.dep -l $*.lst $<
$(NASM) $(NASMOPT) -f elf32 -o $@ -MD $@.dep -l $@.lst $<
%.o64: %.asm $(NASMDEP)
$(NASM) $(NASMOPT) -f elf64 -o $@ -MD $@.dep -l $*.lst $<
$(NASM) $(NASMOPT) -f elf64 -o $@ -MD $@.dep -l $@.lst $<
%.obj: %.asm $(NASMDEP)
$(NASM) $(NASMOPT) -f obj -o $@ -MD $@.dep -l $*.lst $<
$(NASM) $(NASMOPT) -f obj -o $@ -MD $@.dep -l $@.lst $<
%.rdf: %.asm $(NASMDEP)
$(NASM) $(NASMOPT) -f rdf -o $@ -MD $@.dep -l $*.lst $<
$(NASM) $(NASMOPT) -f rdf -o $@ -MD $@.dep -l $@.lst $<
%.od: %.obj ../misc/omfdump
../misc/omfdump $< > $@
%.coff: %.asm $(NASMDEP)
$(NASM) $(NASMOPT) -f coff -o $@ -MD $@.dep -l $*.lst $<
$(NASM) $(NASMOPT) -f coff -o $@ -MD $@.dep -l $@.lst $<
%.win32: %.asm $(NASMDEP)
$(NASM) $(NASMOPT) -f win32 -o $@ -MD $@.dep -l $*.lst $<
$(NASM) $(NASMOPT) -f win32 -o $@ -MD $@.dep -l $@.lst $<
%.win64: %.asm $(NASMDEP)
$(NASM) $(NASMOPT) -f win64 -o $@ -MD $@.dep -l $*.lst $<
$(NASM) $(NASMOPT) -f win64 -o $@ -MD $@.dep -l $@.lst $<
%.mo32: %.asm $(NASMDEP)
$(NASM) $(NASMOPT) -f macho32 -o $@ -MD $@.dep -l $*.lst $<
$(NASM) $(NASMOPT) -f macho32 -o $@ -MD $@.dep -l $@.lst $<
%.mo64: %.asm $(NASMDEP)
$(NASM) $(NASMOPT) -f macho64 -o $@ -MD $@.dep -l $*.lst $<
$(NASM) $(NASMOPT) -f macho64 -o $@ -MD $@.dep -l $@.lst $<
%.dbg: %.asm $(NASMDEP)
$(NASM) $(NASMOPT) -f dbg -o $@ -MD $@.dep -l $*.lst $<
$(NASM) $(NASMOPT) -f dbg -o $@ -MD $@.dep -l $@.lst $<
%.asm: %.pl
$(PERL) $< > $@
@ -83,7 +83,7 @@ spotless: clean
# Test for ELF32 shared libraries; assumes an x86 Linux system
#
elfso.o: elfso.asm $(NASMDEP)
$(NASM) $(NASMOPT) -f elf32 -F stabs -o $@ -MD $@.dep -l $*.lst $<
$(NASM) $(NASMOPT) -f elf32 -F stabs -o $@ -MD $@.dep -l $@.lst $<
elfso.so: elfso.o
$(LD) -m elf_i386 -shared -o $@ -MD $@.dep $<
@ -96,7 +96,7 @@ elftest: elftest.c elfso.so
# Test for ELF64 shared libraries; assumes an x86-64 Linux system
#
elf64so.o: elf64so.asm $(NASMDEP)
$(NASM) $(NASMOPT) -f elf64 -F dwarf -o $@ -MD $@.dep -l $*.lst $<
$(NASM) $(NASMOPT) -f elf64 -F dwarf -o $@ -MD $@.dep -l $@.lst $<
elf64so.so: elf64so.o
$(LD) -shared -o $@ -MD $@.dep $<

View File

@ -1,5 +1,7 @@
;Testname=bin; Arguments=-fbin -oabsolute.bin; Files=stdout stderr absolute.bin
%ifmacro org
org 7c00h
%endif
init_foo:
jmp init_bar
nop
@ -15,7 +17,7 @@ init_foo:
nop
nop
nop
init_bar:
mov [b1],dl
mov [b2],edx
@ -33,8 +35,7 @@ init_bar:
nop
nop
ret
absolute init_bar+7
b1: resb 1
b2: resd 6

25
test/ctxlocal.asm Normal file
View File

@ -0,0 +1,25 @@
;;
;; Test of context-local labels
;;
bits 64
extern everywhere ; Test of extern -> global promotion, too
extern tjosan
here:
jz .there
%push foo
jo %$mordor
hlt
%$mordor:
nop
%pop
.there:
ret
everywhere:
ret
global everywhere
tjosan:
ret

10
test/elf_visibility.asm Normal file
View File

@ -0,0 +1,10 @@
global foo
global foo_hidden:function hidden
SECTION .text align=16
foo:
foo_hidden:
foo_label:
ret

View File

@ -4,9 +4,9 @@
; Test of Mach-O subsection_by_symbol
;
%pragma output subsections_via_symbols
%pragma asm gprefix _
%pragma asm lprefix L_
%pragma macho subsections_via_symbols
%pragma macho gprefix _
%pragma macho lprefix L.
bits 32

12
test/v4.asm Normal file
View File

@ -0,0 +1,12 @@
bits 64
v4fmaddps zmm0,zmm1+3,[rax]
v4fnmaddps zmm2,zmm3,[rax]
v4fmaddss zmm4,zmm5+3,[rax]
v4fnmaddss zmm6,zmm7+3,[rax]
v4dpwssds zmm8,zmm9,[rax]
v4dpwssd zmm10,zmm11+3,[rax]
v4dpwssd zmm10+0,zmm11+3,[rax]
; v4dpwssd zmm10+1,zmm11+3,[rax]
; v4dpwssd zmm10,zmm11+4,[rax]
; v4dpwssd zmm10,zmm11+7,[rax]

View File

@ -51,6 +51,9 @@ $barrier = "#-- Everything below is generated by mkdep.pl - do not edit --#\n";
# This converts from filenames to full pathnames for our dependencies
%dep_path = {};
# List of files that cannot be found; these *must* be excluded
@must_exclude = ();
#
# Scan files for dependencies
#
@ -70,7 +73,8 @@ sub scandeps($) {
if ( $line =~ /^\s*\#\s*include\s+\"(.*)\"\s*$/ ) {
my $nf = $1;
if (!defined($dep_path{$nf})) {
die "$0: cannot determine path for dependency: $file -> $nf\n";
push(@must_exclude, $nf);
next;
}
$nf = $dep_path{$nf};
$mdeps{$nf}++;
@ -138,7 +142,7 @@ sub _insert_deps($$) {
my $selfrule = 0;
my $do_external = 0;
my $maxline = 78; # Seems like a reasonable default
my @exclude = (); # Don't exclude anything
my %exclude = (); # Don't exclude anything
my @genhdrs = ();
my $external = undef;
my $raw_output = 0;
@ -165,7 +169,7 @@ sub _insert_deps($$) {
} elsif ( $parm eq 'continuation' ) {
$cont = $val;
} elsif ( $parm eq 'exclude' ) {
@exclude = split(/\,/, $val);
$excludes{$val}++;
} elsif ( $parm eq 'include-command' ) {
$include_command = $val;
} elsif ( $parm eq 'external' ) {
@ -201,10 +205,6 @@ sub _insert_deps($$) {
}
my $e;
my %do_exclude = ();
foreach $e (@exclude) {
$do_exclude{$e} = 1;
}
foreach my $dfile ($external, sort(keys(%deps)) ) {
my $ofile;
@ -222,7 +222,7 @@ sub _insert_deps($$) {
my $len = length($ofile);
print $out $ofile;
foreach my $dep (@deps) {
unless ($do_exclude{$dep}) {
unless ($excludes{$dep}) {
my $str = convert_file($dep, $sep);
my $sl = length($str)+1;
if ( $len+$sl > $maxline-2 ) {

View File

@ -1,7 +1,7 @@
#!/usr/bin/perl
## --------------------------------------------------------------------------
##
## Copyright 1996-2016 The NASM Authors - All Rights Reserved
## Copyright 1996-2018 The NASM Authors - All Rights Reserved
## See the file AUTHORS included with the NASM distribution for
## the specific copyright holders.
##
@ -142,7 +142,15 @@ my %insns_flag_bit = (
"AVX512VBMI" => [$f++, "AVX-512 VBMI instructions"],
"AES" => [$f++, "AES instructions"],
"VAES" => [$f++, "AES AVX instructions"],
"VPCLMULQDQ" => [$f++, "Carry-Less Multiplication extention"],
"VPCLMULQDQ" => [$f++, "AVX Carryless Multiplication"],
"GFNI" => [$f++, "Galois Field instructions"],
"AVX512VBMI2" => [$f++, "AVX-512 VBMI2 instructions"],
"AVX512VNNI" => [$f++, "AVX-512 VNNI instructions"],
"AVX512BITALG" => [$f++, "AVX-512 Bit Algorithm instructions"],
"AVX512VPOPCNTDQ" => [$f++, "AVX-512 VPOPCNTD/VPOPCNTQ"],
"AVX5124FMAPS" => [$f++, "AVX-512 4-iteration multiply-add"],
"AVX5124VNNIW" => [$f++, "AVX-512 4-iteration dot product"],
"SGX" => [$f++, "Intel Software Guard Extensions (SGX)"],
# Put these last
"OBSOLETE" => [$f++, "Instruction removed from architecture"],

View File

@ -2093,7 +2093,6 @@ VAESENCLAST zmmreg,zmmreg*,zmmrm512 [rvm:fv: evex.nds.512.66.0f38.wig dd /r] AV
VAESDEC zmmreg,zmmreg*,zmmrm512 [rvm:fv: evex.nds.512.66.0f38.wig de /r] AVX512,VAES,FUTURE
VAESDECLAST zmmreg,zmmreg*,zmmrm512 [rvm:fv: evex.nds.512.66.0f38.wig df /r] AVX512,VAES,FUTURE
;# Intel AVX instructions
VADDPD xmmreg,xmmreg*,xmmrm128 [rvm: vex.nds.128.66.0f 58 /r] AVX,SANDYBRIDGE
VADDPD ymmreg,ymmreg*,ymmrm256 [rvm: vex.nds.256.66.0f 58 /r] AVX,SANDYBRIDGE
@ -5198,6 +5197,156 @@ PCOMMIT void [ 66 0f ae f8]
; AMD Zen v1
CLZERO void [ 0f 01 fc] FUTURE,AMD
;# Processor trace write
PTWRITE rm32 [m: np 0f ae /4] FUTURE
PTWRITE rm64 [m: o64 np 0f ae /4] X64,FUTURE
;# Instructions from the Intel Instruction Set Extensions,
;# doc 319433-034 May 2018
CLDEMOTE mem [m: np 0f 1c /0] FUTURE
MOVDIRI mem32,reg32 [mr: np 0f 38 f9 /r] FUTURE,SD
MOVDIRI mem64,reg64 [mr: o64 0f 38 f9 /r] FUTURE,X64,SQ
MOVDIR64B reg16,mem512 [rm: a16 66 0f 38 f8 /r] FUTURE,NOLONG
MOVDIR64B reg32,mem512 [rm: a32 66 0f 38 f8 /r] FUTURE
MOVDIR64B reg64,mem512 [rm: a64 66 0f 38 f8 /r] FUTURE,X64
PCONFIG void [ np 0f 01 c5] FUTURE
TPAUSE reg32 [m: 66 0f ae /6] FUTURE
TPAUSE reg32,reg_edx,reg_eax [m--: 66 0f ae /6] FUTURE,ND
UMONITOR reg16 [m: a16 f3 0f ae /6] FUTURE,NOLONG
UMONITOR reg32 [m: a32 f3 0f ae /6] FUTURE
UMONITOR reg64 [m: a64 f3 0f ae /6] FUTURE,X64
UMWAIT reg32 [m: f2 0f ae /6] FUTURE
UMWAIT reg32,reg_edx,reg_eax [m--: f2 0f ae /6] FUTURE,ND
WBNOINVD void [ f3 0f 09] FUTURE
;# Galois field operations (GFNI)
GF2P8AFFINEINVQB xmmreg,xmmrm128,imm8 [rmi: 66 0f 3a cf /r ib] GFNI,SSE,FUTURE
VGF2P8AFFINEINVQB xmmreg,xmmreg*,xmmrm128,imm8 [rvmi: vex.nds.128.66.0f3a.w1 cf /r ib] GFNI,AVX,FUTURE
VGF2P8AFFINEINVQB ymmreg,ymmreg*,ymmrm256,imm8 [rvmi: vex.nds.256.66.0f3a.w1 cf /r ib] GFNI,AVX,FUTURE
VGF2P8AFFINEINVQB xmmreg|mask|z,xmmreg*,xmmrm128|b64,imm8 [rvmi:fv: evex.nds.128.66.0f3a.w1 cf /r ib] GFNI,AVX512VL,FUTURE
VGF2P8AFFINEINVQB ymmreg|mask|z,ymmreg*,ymmrm256|b64,imm8 [rvmi:fv: evex.nds.256.66.0f3a.w1 cf /r ib] GFNI,AVX512VL,FUTURE
VGF2P8AFFINEINVQB zmmreg|mask|z,zmmreg*,zmmrm512|b64,imm8 [rvmi:fv: evex.nds.512.66.0f3a.w1 cf /r ib] GFNI,AVX512,FUTURE
GF2P8AFFINEQB xmmreg,xmmrm128,imm8 [rmi: 66 0f 3a ce /r ib] GFNI,SSE,FUTURE
VGF2P8AFFINEQB xmmreg,xmmreg*,xmmrm128,imm8 [rvmi: vex.nds.128.66.0f3a.w1 ce /r ib] GFNI,AVX,FUTURE
VGF2P8AFFINEQB ymmreg,ymmreg*,ymmrm256,imm8 [rvmi: vex.nds.256.66.0f3a.w1 ce /r ib] GFNI,AVX,FUTURE
VGF2P8AFFINEQB xmmreg|mask|z,xmmreg*,xmmrm128|b64,imm8 [rvmi:fv: evex.nds.128.66.0f3a.w1 ce /r ib] GFNI,AVX512VL,FUTURE
VGF2P8AFFINEQB ymmreg|mask|z,ymmreg*,ymmrm256|b64,imm8 [rvmi:fv: evex.nds.256.66.0f3a.w1 ce /r ib] GFNI,AVX512VL,FUTURE
VGF2P8AFFINEQB zmmreg|mask|z,zmmreg*,zmmrm512|b64,imm8 [rvmi:fv: evex.nds.512.66.0f3a.w1 ce /r ib] GFNI,AVX512,FUTURE
GF2P8MULB xmmreg,xmmrm128 [rm: 66 0f 38 cf /r] GFNI,SSE,FUTURE
VGF2P8MULB xmmreg,xmmreg*,xmmrm128 [rvm: vex.nds.128.66.0f38.w0 cf /r] GFNI,AVX,FUTURE
VGF2P8MULB ymmreg,ymmreg*,ymmrm256 [rvm: vex.nds.256.66.0f38.w0 cf /r] GFNI,AVX,FUTURE
VGF2P8MULB xmmreg|mask|z,xmmreg*,xmmrm128 [rvm:fvm: evex.nds.128.66.0f38.w0 cf /r] GFNI,AVX512VL,FUTURE
VGF2P8MULB ymmreg|mask|z,ymmreg*,ymmrm256 [rvm:fvm: evex.nds.256.66.0f38.w0 cf /r] GFNI,AVX512VL,FUTURE
VGF2P8MULB zmmreg|mask|z,zmmreg*,zmmrm512 [rvm:fvm: evex.nds.512.66.0f38.w0 cf /r] GFNI,AVX512,FUTURE
;# AVX512 Vector Bit Manipulation Instructions 2
VPCOMPRESSB mem128|mask,xmmreg [mr:t1s: evex.128.66.0f38.w0 63 /r] AVX512VBMI2,AVX512VL,FUTURE
VPCOMPRESSB mem256|mask,ymmreg [mr:t1s: evex.256.66.0f38.w0 63 /r] AVX512VBMI2,AVX512VL,FUTURE
VPCOMPRESSB mem512|mask,zmmreg [mr:t1s: evex.512.66.0f38.w0 63 /r] AVX512VBMI2,FUTURE
VPCOMPRESSB xmmreg|mask|z,xmmreg [mr: evex.128.66.0f38.w0 63 /r] AVX512VBMI2,AVX512VL,FUTURE
VPCOMPRESSB ymmreg|mask|z,ymmreg [mr: evex.256.66.0f38.w0 63 /r] AVX512VBMI2,AVX512VL,FUTURE
VPCOMPRESSB zmmreg|mask|z,zmmreg [mr: evex.512.66.0f38.w0 63 /r] AVX512VBMI2,FUTURE
VPCOMPRESSW mem128|mask,xmmreg [mr:t1s: evex.128.66.0f38.w1 63 /r] AVX512VBMI2,AVX512VL,FUTURE
VPCOMPRESSW mem256|mask,ymmreg [mr:t1s: evex.256.66.0f38.w1 63 /r] AVX512VBMI2,AVX512VL,FUTURE
VPCOMPRESSW mem512|mask,zmmreg [mr:t1s: evex.512.66.0f38.w1 63 /r] AVX512VBMI2,FUTURE
VPCOMPRESSW xmmreg|mask|z,xmmreg [mr: evex.128.66.0f38.w1 63 /r] AVX512VBMI2,AVX512VL,FUTURE
VPCOMPRESSW ymmreg|mask|z,ymmreg [mr: evex.256.66.0f38.w1 63 /r] AVX512VBMI2,AVX512VL,FUTURE
VPCOMPRESSW zmmreg|mask|z,zmmreg [mr: evex.512.66.0f38.w1 63 /r] AVX512VBMI2,FUTURE
VPEXPANDB mem128|mask,xmmreg [mr:t1s: evex.128.66.0f38.w0 62 /r] AVX512VBMI2,AVX512VL,FUTURE
VPEXPANDB mem256|mask,ymmreg [mr:t1s: evex.256.66.0f38.w0 62 /r] AVX512VBMI2,AVX512VL,FUTURE
VPEXPANDB mem512|mask,zmmreg [mr:t1s: evex.512.66.0f38.w0 62 /r] AVX512VBMI2,FUTURE
VPEXPANDB xmmreg|mask|z,xmmreg [mr: evex.128.66.0f38.w0 62 /r] AVX512VBMI2,AVX512VL,FUTURE
VPEXPANDB ymmreg|mask|z,ymmreg [mr: evex.256.66.0f38.w0 62 /r] AVX512VBMI2,AVX512VL,FUTURE
VPEXPANDB zmmreg|mask|z,zmmreg [mr: evex.512.66.0f38.w0 62 /r] AVX512VBMI2,FUTURE
VPEXPANDW mem128|mask,xmmreg [mr:t1s: evex.128.66.0f38.w1 62 /r] AVX512VBMI2,AVX512VL,FUTURE
VPEXPANDW mem256|mask,ymmreg [mr:t1s: evex.256.66.0f38.w1 62 /r] AVX512VBMI2,AVX512VL,FUTURE
VPEXPANDW mem512|mask,zmmreg [mr:t1s: evex.512.66.0f38.w1 62 /r] AVX512VBMI2,FUTURE
VPEXPANDW xmmreg|mask|z,xmmreg [mr: evex.128.66.0f38.w1 62 /r] AVX512VBMI2,AVX512VL,FUTURE
VPEXPANDW ymmreg|mask|z,ymmreg [mr: evex.256.66.0f38.w1 62 /r] AVX512VBMI2,AVX512VL,FUTURE
VPEXPANDW zmmreg|mask|z,zmmreg [mr: evex.512.66.0f38.w1 62 /r] AVX512VBMI2,FUTURE
VPSHLDW xmmreg|mask|z,xmmreg*,xmmrm128,imm8 [rvmi:fvm: evex.nds.128.66.0f3a.w1 70 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHLDW ymmreg|mask|z,ymmreg*,ymmrm256,imm8 [rvmi:fvm: evex.nds.256.66.0f3a.w1 70 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHLDW zmmreg|mask|z,zmmreg*,zmmrm512,imm8 [rvmi:fvm: evex.nds.512.66.0f3a.w1 70 /r ib] AVX512VBMI2,FUTURE
VPSHLDD xmmreg|mask|z,xmmreg*,xmmrm128|b32,imm8 [rvmi:fv: evex.nds.128.66.0f3a.w0 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHLDD ymmreg|mask|z,ymmreg*,ymmrm256|b32,imm8 [rvmi:fv: evex.nds.256.66.0f3a.w0 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHLDD zmmreg|mask|z,zmmreg*,zmmrm512|b32,imm8 [rvmi:fv: evex.nds.512.66.0f3a.w0 71 /r ib] AVX512VBMI2,FUTURE
VPSHLDQ xmmreg|mask|z,xmmreg*,xmmrm128|b64,imm8 [rvmi:fv: evex.nds.128.66.0f3a.w1 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHLDQ ymmreg|mask|z,ymmreg*,ymmrm256|b64,imm8 [rvmi:fv: evex.nds.256.66.0f3a.w1 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHLDQ zmmreg|mask|z,zmmreg*,zmmrm512|b64,imm8 [rvmi:fv: evex.nds.512.66.0f3a.w1 71 /r ib] AVX512VBMI2,FUTURE
VPSHLDVW xmmreg|mask|z,xmmreg*,xmmrm128 [rvmi:fvm: evex.dds.128.66.0f38.w1 70 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHLDVW ymmreg|mask|z,ymmreg*,ymmrm256 [rvmi:fvm: evex.dds.256.66.0f38.w1 70 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHLDVW zmmreg|mask|z,zmmreg*,zmmrm512 [rvmi:fvm: evex.dds.512.66.0f38.w1 70 /r ib] AVX512VBMI2,FUTURE
VPSHLDVD xmmreg|mask|z,xmmreg*,xmmrm128|b32 [rvmi:fv: evex.dds.128.66.0f38.w0 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHLDVD ymmreg|mask|z,ymmreg*,ymmrm256|b32 [rvmi:fv: evex.dds.256.66.0f38.w0 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHLDVD zmmreg|mask|z,zmmreg*,zmmrm512|b32 [rvmi:fv: evex.dds.512.66.0f38.w0 71 /r ib] AVX512VBMI2,FUTURE
VPSHLDVQ xmmreg|mask|z,xmmreg*,xmmrm128|b64 [rvmi:fv: evex.dds.128.66.0f38.w1 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHLDVQ ymmreg|mask|z,ymmreg*,ymmrm256|b64 [rvmi:fv: evex.dds.256.66.0f38.w1 71 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHLDVQ zmmreg|mask|z,zmmreg*,zmmrm512|b64 [rvmi:fv: evex.dds.512.66.0f38.w1 71 /r ib] AVX512VBMI2,FUTURE
VPSHRDW xmmreg|mask|z,xmmreg*,xmmrm128,imm8 [rvmi:fvm: evex.nds.128.66.0f3a.w1 72 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHRDW ymmreg|mask|z,ymmreg*,ymmrm256,imm8 [rvmi:fvm: evex.nds.256.66.0f3a.w1 72 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHRDW zmmreg|mask|z,zmmreg*,zmmrm512,imm8 [rvmi:fvm: evex.nds.512.66.0f3a.w1 72 /r ib] AVX512VBMI2,FUTURE
VPSHRDD xmmreg|mask|z,xmmreg*,xmmrm128|b32,imm8 [rvmi:fv: evex.nds.128.66.0f3a.w0 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHRDD ymmreg|mask|z,ymmreg*,ymmrm256|b32,imm8 [rvmi:fv: evex.nds.256.66.0f3a.w0 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHRDD zmmreg|mask|z,zmmreg*,zmmrm512|b32,imm8 [rvmi:fv: evex.nds.512.66.0f3a.w0 73 /r ib] AVX512VBMI2,FUTURE
VPSHRDQ xmmreg|mask|z,xmmreg*,xmmrm128|b64,imm8 [rvmi:fv: evex.nds.128.66.0f3a.w1 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHRDQ ymmreg|mask|z,ymmreg*,ymmrm256|b64,imm8 [rvmi:fv: evex.nds.256.66.0f3a.w1 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHRDQ zmmreg|mask|z,zmmreg*,zmmrm512|b64,imm8 [rvmi:fv: evex.nds.512.66.0f3a.w1 73 /r ib] AVX512VBMI2,FUTURE
VPSHRDVW xmmreg|mask|z,xmmreg*,xmmrm128 [rvmi:fvm: evex.dds.128.66.0f38.w1 72 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHRDVW ymmreg|mask|z,ymmreg*,ymmrm256 [rvmi:fvm: evex.dds.256.66.0f38.w1 72 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHRDVW zmmreg|mask|z,zmmreg*,zmmrm512 [rvmi:fvm: evex.dds.512.66.0f38.w1 72 /r ib] AVX512VBMI2,FUTURE
VPSHRDVD xmmreg|mask|z,xmmreg*,xmmrm128|b32 [rvmi:fv: evex.dds.128.66.0f38.w0 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHRDVD ymmreg|mask|z,ymmreg*,ymmrm256|b32 [rvmi:fv: evex.dds.256.66.0f38.w0 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHRDVD zmmreg|mask|z,zmmreg*,zmmrm512|b32 [rvmi:fv: evex.dds.512.66.0f38.w0 73 /r ib] AVX512VBMI2,FUTURE
VPSHRDVQ xmmreg|mask|z,xmmreg*,xmmrm128|b64 [rvmi:fv: evex.dds.128.66.0f38.w1 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHRDVQ ymmreg|mask|z,ymmreg*,ymmrm256|b64 [rvmi:fv: evex.dds.256.66.0f38.w1 73 /r ib] AVX512VBMI2,AVX512VL,FUTURE
VPSHRDVQ zmmreg|mask|z,zmmreg*,zmmrm512|b64 [rvmi:fv: evex.dds.512.66.0f38.w1 73 /r ib] AVX512VBMI2,FUTURE
;# AVX512 VNNI
VPDPBUSD xmmreg|mask|z,xmmreg*,xmmrm128|b32 [rvm:fv: evex.dds.128.66.0f38.w0 50 /r] AVX512VNNI,AVX512VL,FUTURE
VPDPBUSD ymmreg|mask|z,ymmreg*,ymmrm256|b32 [rvm:fv: evex.dds.256.66.0f38.w0 50 /r] AVX512VNNI,AVX512VL,FUTURE
VPDPBUSD zmmreg|mask|z,zmmreg*,zmmrm512|b32 [rvm:fv: evex.dds.512.66.0f38.w0 50 /r] AVX512VNNI,FUTURE
VPDPBUSDS xmmreg|mask|z,xmmreg*,xmmrm128|b32 [rvm:fv: evex.dds.128.66.0f38.w0 51 /r] AVX512VNNI,AVX512VL,FUTURE
VPDPBUSDS ymmreg|mask|z,ymmreg*,ymmrm256|b32 [rvm:fv: evex.dds.256.66.0f38.w0 51 /r] AVX512VNNI,AVX512VL,FUTURE
VPDPBUSDS zmmreg|mask|z,zmmreg*,zmmrm512|b32 [rvm:fv: evex.dds.512.66.0f38.w0 51 /r] AVX512VNNI,FUTURE
VPDPWSSD xmmreg|mask|z,xmmreg*,xmmrm128|b32 [rvm:fv: evex.dds.128.66.0f38.w0 52 /r] AVX512VNNI,AVX512VL,FUTURE
VPDPWSSD ymmreg|mask|z,ymmreg*,ymmrm256|b32 [rvm:fv: evex.dds.256.66.0f38.w0 52 /r] AVX512VNNI,AVX512VL,FUTURE
VPDPWSSD zmmreg|mask|z,zmmreg*,zmmrm512|b32 [rvm:fv: evex.dds.512.66.0f38.w0 52 /r] AVX512VNNI,FUTURE
VPDPWSSDS xmmreg|mask|z,xmmreg*,xmmrm128|b32 [rvm:fv: evex.dds.128.66.0f38.w0 53 /r] AVX512VNNI,AVX512VL,FUTURE
VPDPWSSDS ymmreg|mask|z,ymmreg*,ymmrm256|b32 [rvm:fv: evex.dds.256.66.0f38.w0 53 /r] AVX512VNNI,AVX512VL,FUTURE
VPDPWSSDS zmmreg|mask|z,zmmreg*,zmmrm512|b32 [rvm:fv: evex.dds.512.66.0f38.w0 53 /r] AVX512VNNI,FUTURE
;# AVX512 Bit Algorithms
VPOPCNTB xmmreg|mask|z,xmmrm128 [rm:fvm: evex.128.66.0f38.w0 54 /r] AVX512BITALG,AVX512VL,FUTURE
VPOPCNTB ymmreg|mask|z,ymmrm256 [rm:fvm: evex.256.66.0f38.w0 54 /r] AVX512BITALG,AVX512VL,FUTURE
VPOPCNTB zmmreg|mask|z,zmmrm512 [rm:fvm: evex.512.66.0f38.w0 54 /r] AVX512BITALG,FUTURE
VPOPCNTW xmmreg|mask|z,xmmrm128 [rm:fvm: evex.128.66.0f38.w1 54 /r] AVX512BITALG,AVX512VL,FUTURE
VPOPCNTW ymmreg|mask|z,ymmrm256 [rm:fvm: evex.256.66.0f38.w1 54 /r] AVX512BITALG,AVX512VL,FUTURE
VPOPCNTW zmmreg|mask|z,zmmrm512 [rm:fvm: evex.512.66.0f38.w1 54 /r] AVX512BITALG,FUTURE
VPOPCNTD xmmreg|mask|z,xmmrm128 [rm:fv: evex.128.66.0f38.w0 55 /r] AVX512VPOPCNTDQ,AVX512VL,FUTURE
VPOPCNTD ymmreg|mask|z,ymmrm256 [rm:fv: evex.256.66.0f38.w0 55 /r] AVX512VPOPCNTDQ,AVX512VL,FUTURE
VPOPCNTD zmmreg|mask|z,zmmrm512 [rm:fv: evex.512.66.0f38.w0 55 /r] AVX512VPOPCNTDQ,FUTURE
VPOPCNTQ xmmreg|mask|z,xmmrm128 [rm:fv: evex.128.66.0f38.w1 55 /r] AVX512VPOPCNTDQ,AVX512VL,FUTURE
VPOPCNTQ ymmreg|mask|z,ymmrm256 [rm:fv: evex.256.66.0f38.w1 55 /r] AVX512VPOPCNTDQ,AVX512VL,FUTURE
VPOPCNTQ zmmreg|mask|z,zmmrm512 [rm:fv: evex.512.66.0f38.w1 55 /r] AVX512VPOPCNTDQ,FUTURE
VPSHUFBITQMB kreg|mask,xmmreg,xmmrm128 [rvm:fvm: evex.nds.128.66.0f38.w0 8f /r] AVX512BITALG,AVX512VL,FUTURE
VPSHUFBITQMB kreg|mask,ymmreg,ymmrm256 [rvm:fvm: evex.nds.256.66.0f38.w0 8f /r] AVX512BITALG,AVX512VL,FUTURE
VPSHUFBITQMB kreg|mask,zmmreg,zmmrm512 [rvm:fvm: evex.nds.512.66.0f38.w0 8f /r] AVX512BITALG,FUTURE
;# AVX512 4-iteration Multiply-Add
V4FMADDPS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 9a /r] AVX5124FMAPS,FUTURE,SO
V4FNMADDPS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 aa /r] AVX5124FMAPS,FUTURE,SO
V4FMADDSS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.lig.f2.0f38.w0 9b /r] AVX5124FMAPS,FUTURE,SO
V4FNMADDSS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.lig.f2.0f38.w0 ab /r] AVX5124FMAPS,FUTURE,SO
;# AVX512 4-iteration Dot Product
V4DPWSSDS zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 53 /r] AVX5124VNNIW,FUTURE,SO
V4DPWSSD zmmreg|mask|z,zmmreg|rs4,mem [rvm:m128:evex.dds.512.f2.0f38.w0 52 /r] AVX5124VNNIW,FUTURE,SO
;# Intel Software Guard Extensions (SGX)
ENCLS void [ np 0f 01 cf] SGX,FUTURE
ENCLU void [ np 0f 01 d7] SGX,FUTURE
ENCLV void [ np 0f 01 c0] SGX,FUTURE
;# Systematic names for the hinting nop instructions
; These should be last in the file
HINT_NOP0 rm16 [m: o16 0f 18 /0] P6,UNDOC