mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-01-18 16:25:05 +08:00
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:
commit
f7b44f6092
1
.gitignore
vendored
1
.gitignore
vendored
@ -40,6 +40,7 @@ TAGS
|
||||
/*.1
|
||||
/Makefile
|
||||
/asm/directbl.c
|
||||
/asm/directbl.h
|
||||
/asm/directiv.h
|
||||
/asm/pptok.c
|
||||
/asm/pptok.h
|
||||
|
35
Makefile.in
35
Makefile.in
@ -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:
|
||||
|
@ -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 --#
|
||||
|
@ -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;
|
||||
|
@ -399,6 +399,7 @@ bool process_directives(char *directive)
|
||||
"in pass two");
|
||||
in_absolute = true;
|
||||
location.segment = NO_SEG;
|
||||
location.offset = absolute.offset;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -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}
|
||||
|
@ -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;
|
||||
}
|
||||
|
30
asm/float.c
30
asm/float.c
@ -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;
|
||||
|
66
asm/labels.c
66
asm/labels.c
@ -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, ©offset);
|
||||
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;
|
||||
|
100
asm/nasm.c
100
asm/nasm.c
@ -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, ¶m, 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++) {
|
||||
|
54
asm/parser.c
54
asm/parser.c
@ -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;
|
||||
|
||||
|
30
asm/pragma.c
30
asm/pragma.c
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
157
doc/nasmdoc.src
157
doc/nasmdoc.src
@ -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
|
||||
|
@ -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)
|
||||
|
30
doc/pspdf.pl
30
doc/pspdf.pl
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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? */
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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 */
|
||||
|
@ -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 $<
|
||||
|
@ -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
25
test/ctxlocal.asm
Normal 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
10
test/elf_visibility.asm
Normal file
@ -0,0 +1,10 @@
|
||||
global foo
|
||||
global foo_hidden:function hidden
|
||||
|
||||
SECTION .text align=16
|
||||
|
||||
foo:
|
||||
foo_hidden:
|
||||
foo_label:
|
||||
ret
|
||||
|
@ -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
12
test/v4.asm
Normal 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]
|
@ -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 ) {
|
||||
|
@ -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"],
|
||||
|
151
x86/insns.dat
151
x86/insns.dat
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user