summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrill Gorcunov <gorcunov@gmail.com>2013-11-09 22:16:11 +0400
committerCyrill Gorcunov <gorcunov@gmail.com>2013-11-10 00:24:29 +0400
commit4344393e88c9cd7818fbfff79f3725fa629049c1 (patch)
treeafaad08284211a4f858ab515a2d9f9a710dc0a71
parent3b0f2c996ef31805ca998951376e70ae17afdfca (diff)
downloadnasm-4344393e88c9cd7818fbfff79f3725fa629049c1.tar.gz
iflag: Start using new instruction flags engine
Here we start using instruction flags generator. Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
-rw-r--r--Makefile.in12
-rw-r--r--Mkfiles/msvc.mak11
-rw-r--r--Mkfiles/netware.mak5
-rw-r--r--Mkfiles/openwcom.mak12
-rw-r--r--Mkfiles/owlinux.mak11
-rw-r--r--assemble.c49
-rw-r--r--assemble.h11
-rw-r--r--disasm.c15
-rw-r--r--disasm.h4
-rw-r--r--insns.h112
-rwxr-xr-xinsns.pl25
-rw-r--r--nasm.c99
-rw-r--r--ndisasm.c23
13 files changed, 173 insertions, 216 deletions
diff --git a/Makefile.in b/Makefile.in
index d692dd2b..467f3562 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -89,10 +89,11 @@ NASM = nasm.$(O) nasmlib.$(O) ver.$(O) \
strfunc.$(O) tokhash.$(O) regvals.$(O) regflags.$(O) \
ilog2.$(O) \
lib/strlcpy.$(O) \
- preproc-nop.$(O)
+ preproc-nop.$(O) \
+ iflag.$(O)
NDISASM = ndisasm.$(O) disasm.$(O) sync.$(O) nasmlib.$(O) ver.$(O) \
- insnsd.$(O) insnsb.$(O) insnsn.$(O) regs.$(O) regdis.$(O)
+ insnsd.$(O) insnsb.$(O) insnsn.$(O) regs.$(O) regdis.$(O) iflag.$(O)
#-- End File Lists --#
all: nasm$(X) ndisasm$(X) manpages rdf
@@ -108,6 +109,10 @@ ndisasm$(X): $(NDISASM) $(XOBJS)
# though, so it isn't necessary to have Perl just to recompile NASM
# from the distribution.
+insns.pl: insns-iflags.pl
+
+iflag.c iflag.h: insns.dat insns.pl
+ $(PERL) $(srcdir)/insns.pl -t $(srcdir)/insns.dat
insnsb.c: insns.dat insns.pl
$(PERL) $(srcdir)/insns.pl -b $(srcdir)/insns.dat
insnsa.c: insns.dat insns.pl
@@ -185,7 +190,8 @@ PERLREQ = macros.c insnsb.c insnsa.c insnsd.c insnsi.h insnsn.c \
regs.c regs.h regflags.c regdis.c regdis.h regvals.c \
tokhash.c tokens.h pptok.h pptok.c pptok.ph \
directiv.c directiv.h \
- version.h version.mac version.mak version.nsh
+ version.h version.mac version.mak version.nsh \
+ iflag.c iflag.h
perlreq: $(PERLREQ)
# Generated manpages, also pregenerated for distribution
diff --git a/Mkfiles/msvc.mak b/Mkfiles/msvc.mak
index a96bd153..e93219fa 100644
--- a/Mkfiles/msvc.mak
+++ b/Mkfiles/msvc.mak
@@ -51,10 +51,11 @@ NASM = nasm.$(O) nasmlib.$(O) ver.$(O) \
strfunc.$(O) tokhash.$(O) regvals.$(O) regflags.$(O) \
ilog2.$(O) \
lib/strlcpy.$(O) \
- preproc-nop.$(O)
+ preproc-nop.$(O) \
+ iflag.$(O)
NDISASM = ndisasm.$(O) disasm.$(O) sync.$(O) nasmlib.$(O) ver.$(O) \
- insnsd.$(O) insnsb.$(O) insnsn.$(O) regs.$(O) regdis.$(O)
+ insnsd.$(O) insnsb.$(O) insnsn.$(O) regs.$(O) regdis.$(O) iflag.$(O)
#-- End File Lists --#
all: nasm$(X) ndisasm$(X)
@@ -71,6 +72,10 @@ ndisasm$(X): $(NDISASM)
# though, so it isn't necessary to have Perl just to recompile NASM
# from the distribution.
+insns.pl: insns-iflags.pl
+
+iflag.c iflag.h: insns.dat insns.pl
+ $(PERL) $(srcdir)/insns.pl -t $(srcdir)/insns.dat
insnsb.c: insns.dat insns.pl
$(PERL) $(srcdir)/insns.pl -b $(srcdir)/insns.dat
insnsa.c: insns.dat insns.pl
@@ -142,7 +147,7 @@ directiv.c: directiv.dat directiv.pl perllib/phash.ph
# This allows easier generation of distribution (see dist target).
PERLREQ = macros.c insnsb.c insnsa.c insnsd.c insnsi.h insnsn.c \
regs.c regs.h regflags.c regdis.c regvals.c tokhash.c tokens.h \
- version.h version.mac pptok.h pptok.c
+ version.h version.mac pptok.h pptok.c iflag.c iflag.h
perlreq: $(PERLREQ)
clean:
diff --git a/Mkfiles/netware.mak b/Mkfiles/netware.mak
index 178dbdc3..8615431e 100644
--- a/Mkfiles/netware.mak
+++ b/Mkfiles/netware.mak
@@ -47,10 +47,11 @@ NASM = nasm.o nasmlib.o ver.o \
strfunc.o tokhash.o regvals.o regflags.o \
ilog2.o \
strlcpy.o \
- preproc-nop.o
+ preproc-nop.o \
+ iflag.o
NDISASM = ndisasm.o disasm.o sync.o nasmlib.o ver.o \
- insnsd.o insnsb.o insnsn.o regs.o regdis.o
+ insnsd.o insnsb.o insnsn.o regs.o regdis.o iflag.o
#-- End File Lists --#
NASM_OBJ = $(addprefix $(OBJDIR)/,$(notdir $(NASM))) $(EOLIST)
diff --git a/Mkfiles/openwcom.mak b/Mkfiles/openwcom.mak
index 8a0ffef8..222163d6 100644
--- a/Mkfiles/openwcom.mak
+++ b/Mkfiles/openwcom.mak
@@ -63,10 +63,11 @@ NASM = nasm.$(O) nasmlib.$(O) ver.$(O) &
strfunc.$(O) tokhash.$(O) regvals.$(O) regflags.$(O) &
ilog2.$(O) &
lib/strlcpy.$(O) &
- preproc-nop.$(O)
+ preproc-nop.$(O) &
+ iflag.$(O)
NDISASM = ndisasm.$(O) disasm.$(O) sync.$(O) nasmlib.$(O) ver.$(O) &
- insnsd.$(O) insnsb.$(O) insnsn.$(O) regs.$(O) regdis.$(O)
+ insnsd.$(O) insnsb.$(O) insnsn.$(O) regs.$(O) regdis.$(O) iflag.$(O)
#-- End File Lists --#
what: .SYMBOLIC
@@ -106,6 +107,10 @@ ndisasm$(X): $(NDISASM)
# though, so it isn't necessary to have Perl just to recompile NASM
# from the distribution.
+insns.pl: insns-iflags.pl
+
+iflag.c iflag.h: insns.dat insns.pl
+ $(PERL) $(srcdir)/insns.pl -t $(srcdir)/insns.dat
insnsb.c: insns.dat insns.pl
$(PERL) $(srcdir)/insns.pl -b $(srcdir)/insns.dat
insnsa.c: insns.dat insns.pl
@@ -177,7 +182,8 @@ PERLREQ = pptok.ph macros.c insnsb.c insnsa.c insnsd.c insnsi.h insnsn.c &
regs.c regs.h regflags.c regdis.c regdis.h regvals.c &
tokhash.c tokens.h pptok.h pptok.c &
directiv.c directiv.h &
- version.h version.mac
+ version.h version.mac &
+ iflag.c iflag.h
perlreq: $(PERLREQ) .SYMBOLIC
clean: .SYMBOLIC
diff --git a/Mkfiles/owlinux.mak b/Mkfiles/owlinux.mak
index d04c80d7..04fb90a6 100644
--- a/Mkfiles/owlinux.mak
+++ b/Mkfiles/owlinux.mak
@@ -74,10 +74,11 @@ NASM = nasm.$(O) nasmlib.$(O) ver.$(O) \
strfunc.$(O) tokhash.$(O) regvals.$(O) regflags.$(O) \
ilog2.$(O) \
lib/strlcpy.$(O) \
- preproc-nop.$(O)
+ preproc-nop.$(O) \
+ iflag.$(O)
NDISASM = ndisasm.$(O) disasm.$(O) sync.$(O) nasmlib.$(O) ver.$(O) \
- insnsd.$(O) insnsb.$(O) insnsn.$(O) regs.$(O) regdis.$(O)
+ insnsd.$(O) insnsb.$(O) insnsn.$(O) regs.$(O) regdis.$(O) iflag.$(O)
#-- End File Lists --#
what:
@@ -105,6 +106,10 @@ ndisasm$(X): $(NDISASM)
# though, so it isn't necessary to have Perl just to recompile NASM
# from the distribution.
+insns.pl: insns-iflags.pl
+
+iflag.c iflag.h: insns.dat insns.pl
+ $(PERL) $(srcdir)/insns.pl -t $(srcdir)/insns.dat
insnsb.c: insns.dat insns.pl
$(PERL) $(srcdir)/insns.pl -b $(srcdir)/insns.dat
insnsa.c: insns.dat insns.pl
@@ -167,7 +172,7 @@ pptok.c: pptok.dat pptok.pl perllib/phash.ph
PERLREQ = macros.c insnsb.c insnsa.c insnsd.c insnsi.h insnsn.c \
regs.c regs.h regflags.c regdis.c regdis.h regvals.c \
tokhash.c tokens.h pptok.h pptok.c \
- version.h version.mac
+ version.h version.mac iflag.c iflag.h
perlreq: $(PERLREQ)
clean:
diff --git a/assemble.c b/assemble.c
index 57ef0cdb..b6dccbfc 100644
--- a/assemble.c
+++ b/assemble.c
@@ -214,7 +214,7 @@ typedef struct {
#define GEN_MODRM(mod, reg, rm) \
(((mod) << 6) | (((reg) & 7) << 3) | ((rm) & 7))
-static iflags_t cpu; /* cpu level received from nasm.c */
+static iflag_t cpu; /* cpu level received from nasm.c */
static efunc errfunc;
static struct ofmt *outfmt;
static ListGen *list;
@@ -378,7 +378,7 @@ static bool jmp_match(int32_t segment, int64_t offset, int bits,
return (isize >= -128 && isize <= 127); /* is it byte size? */
}
-int64_t assemble(int32_t segment, int64_t offset, int bits, iflags_t cp,
+int64_t assemble(int32_t segment, int64_t offset, int bits, iflag_t cp,
insn * instruction, struct ofmt *output, efunc error,
ListGen * listgen)
{
@@ -681,7 +681,7 @@ int64_t assemble(int32_t segment, int64_t offset, int bits, iflags_t cp,
return 0;
}
-int64_t insn_size(int32_t segment, int64_t offset, int bits, iflags_t cp,
+int64_t insn_size(int32_t segment, int64_t offset, int bits, iflag_t cp,
insn * instruction, efunc error)
{
const struct itemplate *temp;
@@ -1255,7 +1255,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
length++;
} else if ((ins->rex & REX_L) &&
!(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
- cpu >= IF_X86_64) {
+ iflag_ffs(&cpu) >= IF_X86_64) {
/* LOCK-as-REX.R */
assert_no_prefix(ins, PPS_LOCK);
lockcheck = false; /* Already errored, no need for warning */
@@ -1267,7 +1267,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
}
if (has_prefix(ins, PPS_LOCK, P_LOCK) && lockcheck &&
- (!(temp->flags & IF_LOCK) || !is_class(MEMORY, ins->oprs[0].type))) {
+ (!itemp_has(temp,IF_LOCK) || !is_class(MEMORY, ins->oprs[0].type))) {
errfunc(ERR_WARNING | ERR_WARN_LOCK | ERR_PASS2 ,
"instruction is not lockable");
}
@@ -1946,8 +1946,7 @@ static enum match_result find_match(const struct itemplate **tempp,
m = MOK_GOOD;
else
m = MERR_INVALOP;
- } else if (m == MERR_OPSIZEMISSING &&
- (temp->flags & IF_SMASK) != IF_SX) {
+ } else if (m == MERR_OPSIZEMISSING && !itemp_has(temp, IF_SX)) {
/*
* Missing operand size and a candidate for fuzzy matching...
*/
@@ -2030,7 +2029,7 @@ static enum match_result matches(const struct itemplate *itemp,
/*
* Is it legal?
*/
- if (!(optimizing > 0) && (itemp->flags & IF_OPT))
+ if (!(optimizing > 0) && itemp_has(itemp, IF_OPT))
return MERR_INVALOP;
/*
@@ -2043,29 +2042,29 @@ static enum match_result matches(const struct itemplate *itemp,
/*
* Process size flags
*/
- switch (itemp->flags & IF_SMASK) {
- case IF_SB:
+ switch (itemp_smask(itemp)) {
+ case IF_GENBIT(IF_SB):
asize = BITS8;
break;
- case IF_SW:
+ case IF_GENBIT(IF_SW):
asize = BITS16;
break;
- case IF_SD:
+ case IF_GENBIT(IF_SD):
asize = BITS32;
break;
- case IF_SQ:
+ case IF_GENBIT(IF_SQ):
asize = BITS64;
break;
- case IF_SO:
+ case IF_GENBIT(IF_SO):
asize = BITS128;
break;
- case IF_SY:
+ case IF_GENBIT(IF_SY):
asize = BITS256;
break;
- case IF_SZ:
+ case IF_GENBIT(IF_SZ):
asize = BITS512;
break;
- case IF_SIZE:
+ case IF_GENBIT(IF_SIZE):
switch (bits) {
case 16:
asize = BITS16;
@@ -2086,9 +2085,9 @@ static enum match_result matches(const struct itemplate *itemp,
break;
}
- if (itemp->flags & IF_ARMASK) {
+ if (itemp_armask(itemp)) {
/* S- flags only apply to a specific operand */
- i = ((itemp->flags & IF_ARMASK) >> IF_ARSHFT) - 1;
+ i = itemp_arg(itemp);
memset(size, 0, sizeof size);
size[i] = asize;
} else {
@@ -2149,7 +2148,7 @@ static enum match_result matches(const struct itemplate *itemp,
}
} else if (is_register(instruction->oprs[i].basereg) &&
nasm_regvals[instruction->oprs[i].basereg] >= 16 &&
- !(itemp->flags & IF_AVX512)) {
+ !itemp_has(itemp, IF_AVX512)) {
return MERR_ENCMISMATCH;
}
}
@@ -2160,8 +2159,8 @@ static enum match_result matches(const struct itemplate *itemp,
/*
* Check operand sizes
*/
- if (itemp->flags & (IF_SM | IF_SM2)) {
- oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
+ if (itemp_has(itemp, IF_SM) || itemp_has(itemp, IF_SM2)) {
+ oprs = (itemp_has(itemp, IF_SM2) ? 2 : itemp->operands);
for (i = 0; i < oprs; i++) {
asize = itemp->opd[i] & SIZE_MASK;
if (asize) {
@@ -2183,19 +2182,19 @@ static enum match_result matches(const struct itemplate *itemp,
/*
* Check template is okay at the set cpu level
*/
- if (((itemp->flags & IF_PLEVEL) > cpu))
+ if (iflag_cmp_cpu_level(&insns_flags[itemp->iflag_idx], &cpu) > 0)
return MERR_BADCPU;
/*
* Verify the appropriate long mode flag.
*/
- if ((itemp->flags & (bits == 64 ? IF_NOLONG : IF_LONG)))
+ if (itemp_has(itemp, (bits == 64 ? IF_NOLONG : IF_LONG)))
return MERR_BADMODE;
/*
* If we have a HLE prefix, look for the NOHLE flag
*/
- if ((itemp->flags & IF_NOHLE) &&
+ if (itemp_has(itemp, IF_NOHLE) &&
(has_prefix(instruction, PPS_REP, P_XACQUIRE) ||
has_prefix(instruction, PPS_REP, P_XRELEASE)))
return MERR_BADHLE;
diff --git a/assemble.h b/assemble.h
index 1197d591..381e3ab5 100644
--- a/assemble.h
+++ b/assemble.h
@@ -38,10 +38,11 @@
#ifndef NASM_ASSEMBLE_H
#define NASM_ASSEMBLE_H
-int64_t insn_size(int32_t segment, int64_t offset, int bits, iflags_t cp,
- insn * instruction, efunc error);
-int64_t assemble(int32_t segment, int64_t offset, int bits, iflags_t cp,
- insn * instruction, struct ofmt *output, efunc error,
- ListGen * listgen);
+#include "iflag.h"
+int64_t insn_size(int32_t segment, int64_t offset, int bits, iflag_t cp,
+ insn * instruction, efunc error);
+int64_t assemble(int32_t segment, int64_t offset, int bits, iflag_t cp,
+ insn * instruction, struct ofmt *output, efunc error,
+ ListGen * listgen);
#endif
diff --git a/disasm.c b/disasm.c
index 9a5f9ad4..63453fab 100644
--- a/disasm.c
+++ b/disasm.c
@@ -404,7 +404,7 @@ static int matches(const struct itemplate *t, uint8_t *data,
ins->rex = prefix->rex;
memset(ins->prefixes, 0, sizeof ins->prefixes);
- if (t->flags & (segsize == 64 ? IF_NOLONG : IF_LONG))
+ if (itemp_has(t, (segsize == 64 ? IF_NOLONG : IF_LONG)))
return false;
if (prefix->rep == 0xF2)
@@ -944,7 +944,7 @@ static const char * const condition_name[16] = {
};
int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
- int32_t offset, int autosync, iflags_t prefer)
+ int32_t offset, int autosync, iflag_t *prefer)
{
const struct itemplate * const *p, * const *best_p;
const struct disasm_index *ix;
@@ -955,7 +955,7 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
uint8_t *origdata;
int works;
insn tmp_ins, ins;
- iflags_t goodness, best;
+ iflag_t goodness, best;
int best_pref;
struct prefix_info prefix;
bool end_prefix;
@@ -1096,7 +1096,7 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
}
}
- best = -1; /* Worst possible */
+ iflag_set_all(&best); /* Worst possible */
best_p = NULL;
best_pref = INT_MAX;
@@ -1149,14 +1149,15 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
* selection.
*/
if (works) {
- int i, nprefix;
- goodness = ((*p)->flags & IF_PFMASK) ^ prefer;
+ int i, nprefix;
+ goodness = iflag_pfmask(*p);
+ goodness = iflag_xor(&goodness, prefer);
nprefix = 0;
for (i = 0; i < MAXPREFIX; i++)
if (tmp_ins.prefixes[i])
nprefix++;
if (nprefix < best_pref ||
- (nprefix == best_pref && goodness < best)) {
+ (nprefix == best_pref && iflag_cmp(&goodness, &best) == -1)) {
/* This is the best one found so far */
best = goodness;
best_p = p;
diff --git a/disasm.h b/disasm.h
index 70a9a7bb..fa6e2e2f 100644
--- a/disasm.h
+++ b/disasm.h
@@ -38,10 +38,12 @@
#ifndef NASM_DISASM_H
#define NASM_DISASM_H
+#include "iflag.h"
+
#define INSN_MAX 32 /* one instruction can't be longer than this */
int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
- int32_t offset, int autosync, iflags_t prefer);
+ int32_t offset, int autosync, iflag_t *prefer);
int32_t eatbyte(uint8_t *data, char *output, int outbufsize, int segsize);
#endif
diff --git a/insns.h b/insns.h
index b12d4ebb..13034b2a 100644
--- a/insns.h
+++ b/insns.h
@@ -11,6 +11,7 @@
#include "nasm.h"
#include "tokens.h"
+#include "iflag.h"
/* if changed, ITEMPLATE_END should be also changed accordingly */
struct itemplate {
@@ -19,7 +20,7 @@ struct itemplate {
opflags_t opd[MAX_OPERANDS]; /* bit flags for operand types */
decoflags_t deco[MAX_OPERANDS]; /* bit flags for operand decorators */
const uint8_t *code; /* the code it assembles to */
- iflags_t flags; /* some flags */
+ uint32_t iflag_idx; /* some flags referenced by index */
};
/* Disassembler table structure */
@@ -48,113 +49,8 @@ extern const uint8_t nasm_bytecodes[];
#define ITEMPLATE_END {-1,-1,{-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1},NULL,0}
/*
- * Instruction template flags. These specify which processor
- * targets the instruction is eligible for, whether it is
- * privileged or undocumented, and also specify extra error
- * checking on the matching of the instruction.
- *
- * IF_SM stands for Size Match: any operand whose size is not
- * explicitly specified by the template is `really' intended to be
- * the same size as the first size-specified operand.
- * Non-specification is tolerated in the input instruction, but
- * _wrong_ specification is not.
- *
- * IF_SM2 invokes Size Match on only the first _two_ operands, for
- * three-operand instructions such as SHLD: it implies that the
- * first two operands must match in size, but that the third is
- * required to be _unspecified_.
- *
- * IF_SB invokes Size Byte: operands with unspecified size in the
- * template are really bytes, and so no non-byte specification in
- * the input instruction will be tolerated. IF_SW similarly invokes
- * Size Word, and IF_SD invokes Size Doubleword.
- *
- * (The default state if neither IF_SM nor IF_SM2 is specified is
- * that any operand with unspecified size in the template is
- * required to have unspecified size in the instruction too...)
- *
- * iflags_t is defined to store these flags.
+ * FIXME This are to get rid off!
*/
-
-#define IF_SM 0x00000001UL /* size match */
-#define IF_SM2 0x00000002UL /* size match first two operands */
-#define IF_SB 0x00000004UL /* unsized operands can't be non-byte */
-#define IF_SW 0x00000008UL /* unsized operands can't be non-word */
-#define IF_SD 0x0000000CUL /* unsized operands can't be non-dword */
-#define IF_SQ 0x00000010UL /* unsized operands can't be non-qword */
-#define IF_SO 0x00000014UL /* unsized operands can't be non-oword */
-#define IF_SY 0x00000018UL /* unsized operands can't be non-yword */
-#define IF_SZ 0x0000001CUL /* unsized operands can't be non-zword */
-#define IF_SIZE 0x00000038UL /* unsized operands must match the bitsize */
-#define IF_SX 0x0000003CUL /* unsized operands not allowed */
-#define IF_SMASK 0x0000003CUL /* mask for unsized argument size */
-#define IF_AR0 0x00000040UL /* SB, SW, SD applies to argument 0 */
-#define IF_AR1 0x00000080UL /* SB, SW, SD applies to argument 1 */
-#define IF_AR2 0x000000C0UL /* SB, SW, SD applies to argument 2 */
-#define IF_AR3 0x00000100UL /* SB, SW, SD applies to argument 3 */
-#define IF_AR4 0x00000140UL /* SB, SW, SD applies to argument 4 */
-#define IF_ARMASK 0x000001C0UL /* mask for unsized argument spec */
-#define IF_ARSHFT 6 /* LSB in IF_ARMASK */
-#define IF_OPT 0x00000200UL /* optimizing assembly only */
-/* The next 3 bits aren't actually used for anything */
-#define IF_PRIV 0x00000000UL /* it's a privileged instruction */
-#define IF_SMM 0x00000000UL /* it's only valid in SMM */
-#define IF_PROT 0x00000000UL /* it's protected mode only */
-#define IF_LOCK 0x00000400UL /* lockable if operand 0 is memory */
-#define IF_NOLONG 0x00000800UL /* it's not available in long mode */
-#define IF_LONG 0x00001000UL /* long mode instruction */
-#define IF_NOHLE 0x00002000UL /* HLE prefixes forbidden */
-/* These flags are currently not used for anything - intended for insn set */
-#define IF_UNDOC 0x8000000000UL /* it's an undocumented instruction */
-#define IF_HLE 0x4000000000UL /* HACK NEED TO REORGANIZE THESE BITS */
-#define IF_AVX512 0x2000000000UL /* it's an AVX-512F (512b) instruction */
-#define IF_FPU 0x0100000000UL /* it's an FPU instruction */
-#define IF_MMX 0x0200000000UL /* it's an MMX instruction */
-#define IF_3DNOW 0x0300000000UL /* it's a 3DNow! instruction */
-#define IF_SSE 0x0400000000UL /* it's a SSE (KNI, MMX2) instruction */
-#define IF_SSE2 0x0500000000UL /* it's a SSE2 instruction */
-#define IF_SSE3 0x0600000000UL /* it's a SSE3 (PNI) instruction */
-#define IF_VMX 0x0700000000UL /* it's a VMX instruction */
-#define IF_SSSE3 0x0800000000UL /* it's an SSSE3 instruction */
-#define IF_SSE4A 0x0900000000UL /* AMD SSE4a */
-#define IF_SSE41 0x0A00000000UL /* it's an SSE4.1 instruction */
-#define IF_SSE42 0x0B00000000UL /* HACK NEED TO REORGANIZE THESE BITS */
-#define IF_SSE5 0x0C00000000UL /* HACK NEED TO REORGANIZE THESE BITS */
-#define IF_AVX 0x0D00000000UL /* it's an AVX (128b) instruction */
-#define IF_AVX2 0x0E00000000UL /* it's an AVX2 (256b) instruction */
-#define IF_FMA 0x1000000000UL /* HACK NEED TO REORGANIZE THESE BITS */
-#define IF_BMI1 0x1100000000UL /* HACK NEED TO REORGANIZE THESE BITS */
-#define IF_BMI2 0x1200000000UL /* HACK NEED TO REORGANIZE THESE BITS */
-#define IF_TBM 0x1300000000UL /* HACK NEED TO REORGANIZE THESE BITS */
-#define IF_RTM 0x1400000000UL /* HACK NEED TO REORGANIZE THESE BITS */
-#define IF_INVPCID 0x1500000000UL /* HACK NEED TO REORGANIZE THESE BITS */
-#define IF_AVX512CD (0x1600000000UL|IF_AVX512) /* AVX-512 Conflict Detection insns */
-#define IF_AVX512ER (0x1700000000UL|IF_AVX512) /* AVX-512 Exponential and Reciprocal */
-#define IF_AVX512PF (0x1800000000UL|IF_AVX512) /* AVX-512 Prefetch instructions */
-#define IF_INSMASK 0xFF00000000UL /* the mask for instruction set types */
-#define IF_PMASK 0xFF000000UL /* the mask for processor types */
-#define IF_PLEVEL 0x0F000000UL /* the mask for processor instr. level */
- /* also the highest possible processor */
-#define IF_8086 0x00000000UL /* 8086 instruction */
-#define IF_186 0x01000000UL /* 186+ instruction */
-#define IF_286 0x02000000UL /* 286+ instruction */
-#define IF_386 0x03000000UL /* 386+ instruction */
-#define IF_486 0x04000000UL /* 486+ instruction */
-#define IF_PENT 0x05000000UL /* Pentium instruction */
-#define IF_P6 0x06000000UL /* P6 instruction */
-#define IF_KATMAI 0x07000000UL /* Katmai instructions */
-#define IF_WILLAMETTE 0x08000000UL /* Willamette instructions */
-#define IF_PRESCOTT 0x09000000UL /* Prescott instructions */
-#define IF_X86_64 0x0A000000UL /* x86-64 instruction (long or legacy mode) */
-#define IF_NEHALEM 0x0B000000UL /* Nehalem instruction */
-#define IF_WESTMERE 0x0C000000UL /* Westmere instruction */
-#define IF_SANDYBRIDGE 0x0D000000UL /* Sandy Bridge instruction */
-#define IF_FUTURE 0x0E000000UL /* Future processor (not yet disclosed) */
-#define IF_X64 (IF_LONG|IF_X86_64)
-#define IF_IA64 0x0F000000UL /* IA64 instructions (in x86 mode) */
-#define IF_CYRIX 0x10000000UL /* Cyrix-specific instruction */
-#define IF_AMD 0x20000000UL /* AMD-specific instruction */
-#define IF_SPMASK 0x30000000UL /* specific processor types mask */
-#define IF_PFMASK (IF_INSMASK|IF_SPMASK) /* disassembly "prefer" mask */
+#define iflags_t uint64_t
#endif /* NASM_INSNS_H */
diff --git a/insns.pl b/insns.pl
index 8d1f0ee8..a296d570 100755
--- a/insns.pl
+++ b/insns.pl
@@ -37,6 +37,8 @@
#
# Parse insns.dat and produce generated source code files
+require 'insns-iflags.pl';
+
# Opcode prefixes which need their own opcode tables
# LONGER PREFIXES FIRST!
@disasm_prefixes = qw(0F24 0F25 0F38 0F3A 0F7A 0FA6 0FA7 0F);
@@ -67,7 +69,7 @@ print STDERR "Reading insns.dat...\n";
undef $output;
foreach $arg ( @ARGV ) {
if ( $arg =~ /^\-/ ) {
- if ( $arg =~ /^\-([abdin])$/ ) {
+ if ( $arg =~ /^\-([abdint])$/ ) {
$output = $1;
} else {
die "$0: Unknown option: ${arg}\n";
@@ -393,6 +395,10 @@ if ( !defined($output) || $output eq 'n' ) {
close N;
}
+if ( !defined($output) || $output eq 't') {
+ write_iflags();
+}
+
printf STDERR "Done: %d instructions\n", $insns;
# Count primary bytecodes, for statistics
@@ -424,7 +430,7 @@ sub count_bytecodes(@) {
sub format_insn($$$$$) {
my ($opcode, $operands, $codes, $flags, $relax) = @_;
- my $num, $nd = 0;
+ my $num, $nd = 0, $rawflags, $flagsindex;
my @bytecode;
my $op, @ops, $opp, @opx, @oppx, @decos, @opevex;
my @iflags = ( "FPU", "MMX", "3DNOW", "SSE", "SSE2",
@@ -492,16 +498,23 @@ sub format_insn($$$$$) {
}
# format the flags
- $flags =~ s/,/|IF_/g;
- $flags =~ s/(\|IF_ND|IF_ND\|)//, $nd = 1 if $flags =~ /IF_ND/;
- $flags = "IF_" . $flags;
+ $nd = 1 if $flags =~ /(^|\,)ND($|\,)/;
+ $flags =~ s/(^|\,)ND($|\,)/\1/g;
+ $flags =~ s/(^|\,)X64($|\,)/\1LONG,X86_64\2/g;
+ $flags =~ s/(^|\,)AVX512CD($|\,)/\1AVX512CD,AVX512\2/g;
+ $flags =~ s/(^|\,)AVX512ER($|\,)/\1AVX512ER,AVX512\2/g;
+ $flags =~ s/(^|\,)AVX512PF($|\,)/\1AVX512PF,AVX512\2/g;
+ $rawflags = $flags;
+ $flagsindex = insns_flag_index(split(',',$flags));
+
+ die "Error in flags $rawflags" if not defined($flagsindex);
@bytecode = (decodify($codes, $relax), 0);
push(@bytecode_list, [@bytecode]);
$codes = hexstr(@bytecode);
count_bytecodes(@bytecode);
- ("{I_$opcode, $num, {$operands}, $decorators, \@\@CODES-$codes\@\@, $flags},", $nd);
+ ("{I_$opcode, $num, {$operands}, $decorators, \@\@CODES-$codes\@\@, $flagsindex},", $nd);
}
#
diff --git a/nasm.c b/nasm.c
index 3a0c0508..b83810d2 100644
--- a/nasm.c
+++ b/nasm.c
@@ -60,6 +60,7 @@
#include "labels.h"
#include "output/outform.h"
#include "listing.h"
+#include "iflag.h"
/*
* This is the maximum number of optimization passes to do. If we ever
@@ -74,7 +75,7 @@ struct forwrefinfo { /* info held on forward refs. */
};
static int get_bits(char *value);
-static iflags_t get_cpu(char *cpu_str);
+static iflag_t get_cpu(char *cpu_str);
static void parse_cmdline(int, char **);
static void assemble_file(char *, StrList **);
static void nasm_verror_gnu(int severity, const char *fmt, va_list args);
@@ -106,8 +107,10 @@ static FILE *error_file; /* Where to write error messages */
FILE *ofile = NULL;
int optimizing = MAX_OPTIMIZE; /* number of optimization passes to take */
static int sb, cmd_sb = 16; /* by default */
-static iflags_t cmd_cpu = IF_PLEVEL; /* highest level by default */
-static iflags_t cpu = IF_PLEVEL; /* passed to insn_size & assemble.c */
+
+static iflag_t cpu;
+static iflag_t cmd_cpu;
+
int64_t global_offset_changed; /* referenced in labels.c */
int64_t prev_offset_changed;
int32_t stall_count;
@@ -321,6 +324,9 @@ int main(int argc, char **argv)
time(&official_compile_time);
+ iflag_set(&cpu, IF_PLEVEL);
+ iflag_set(&cmd_cpu, IF_PLEVEL);
+
pass0 = 0;
want_usage = terminate_after_phase = false;
nasm_set_verror(nasm_verror_gnu);
@@ -1187,7 +1193,7 @@ static void assemble_file(char *fname, StrList **depend_ptr)
expr *e;
int pass_max;
- if (cmd_sb == 32 && cmd_cpu < IF_386)
+ if (cmd_sb == 32 && iflag_ffs(&cmd_cpu) < IF_386)
nasm_error(ERR_FATAL, "command line: "
"32-bit segment size requires a higher cpu");
@@ -2006,44 +2012,53 @@ static void usage(void)
fputs("type `nasm -h' for help\n", error_file);
}
-static iflags_t get_cpu(char *value)
+static iflag_t get_cpu(char *value)
{
+ iflag_t r;
+
+ iflag_clear_all(&r);
+
if (!strcmp(value, "8086"))
- return IF_8086;
- if (!strcmp(value, "186"))
- return IF_186;
- if (!strcmp(value, "286"))
- return IF_286;
- if (!strcmp(value, "386"))
- return IF_386;
- if (!strcmp(value, "486"))
- return IF_486;
- if (!strcmp(value, "586") || !nasm_stricmp(value, "pentium"))
- return IF_PENT;
- if (!strcmp(value, "686") ||
- !nasm_stricmp(value, "ppro") ||
- !nasm_stricmp(value, "pentiumpro") || !nasm_stricmp(value, "p2"))
- return IF_P6;
- if (!nasm_stricmp(value, "p3") || !nasm_stricmp(value, "katmai"))
- return IF_KATMAI;
- if (!nasm_stricmp(value, "p4") || /* is this right? -- jrc */
- !nasm_stricmp(value, "willamette"))
- return IF_WILLAMETTE;
- if (!nasm_stricmp(value, "prescott"))
- return IF_PRESCOTT;
- if (!nasm_stricmp(value, "x64") ||
- !nasm_stricmp(value, "x86-64"))
- return IF_X86_64;
- if (!nasm_stricmp(value, "ia64") ||
- !nasm_stricmp(value, "ia-64") ||
- !nasm_stricmp(value, "itanium") ||
- !nasm_stricmp(value, "itanic") || !nasm_stricmp(value, "merced"))
- return IF_IA64;
-
- nasm_error(pass0 < 2 ? ERR_NONFATAL : ERR_FATAL,
- "unknown 'cpu' type");
-
- return IF_PLEVEL; /* the maximum level */
+ iflag_set(&r, IF_8086);
+ else if (!strcmp(value, "186"))
+ iflag_set(&r, IF_186);
+ else if (!strcmp(value, "286"))
+ iflag_set(&r, IF_286);
+ else if (!strcmp(value, "386"))
+ iflag_set(&r, IF_386);
+ else if (!strcmp(value, "486"))
+ iflag_set(&r, IF_486);
+ else if (!strcmp(value, "586") ||
+ !nasm_stricmp(value, "pentium"))
+ iflag_set(&r, IF_PENT);
+ else if (!strcmp(value, "686") ||
+ !nasm_stricmp(value, "ppro") ||
+ !nasm_stricmp(value, "pentiumpro") ||
+ !nasm_stricmp(value, "p2"))
+ iflag_set(&r, IF_P6);
+ else if (!nasm_stricmp(value, "p3") ||
+ !nasm_stricmp(value, "katmai"))
+ iflag_set(&r, IF_KATMAI);
+ else if (!nasm_stricmp(value, "p4") || /* is this right? -- jrc */
+ !nasm_stricmp(value, "willamette"))
+ iflag_set(&r, IF_WILLAMETTE);
+ else if (!nasm_stricmp(value, "prescott"))
+ iflag_set(&r, IF_PRESCOTT);
+ else if (!nasm_stricmp(value, "x64") ||
+ !nasm_stricmp(value, "x86-64"))
+ iflag_set(&r, IF_X86_64);
+ else if (!nasm_stricmp(value, "ia64") ||
+ !nasm_stricmp(value, "ia-64") ||
+ !nasm_stricmp(value, "itanium")||
+ !nasm_stricmp(value, "itanic") ||
+ !nasm_stricmp(value, "merced"))
+ iflag_set(&r, IF_IA64);
+ else {
+ iflag_set(&r, IF_PLEVEL);
+ nasm_error(pass0 < 2 ? ERR_NONFATAL : ERR_FATAL,
+ "unknown 'cpu' type");
+ }
+ return r;
}
static int get_bits(char *value)
@@ -2053,13 +2068,13 @@ static int get_bits(char *value)
if ((i = atoi(value)) == 16)
return i; /* set for a 16-bit segment */
else if (i == 32) {
- if (cpu < IF_386) {
+ if (iflag_ffs(&cpu) < IF_386) {
nasm_error(ERR_NONFATAL,
"cannot specify 32-bit segment on processor below a 386");
i = 16;
}
} else if (i == 64) {
- if (cpu < IF_X86_64) {
+ if (iflag_ffs(&cpu) < IF_X86_64) {
nasm_error(ERR_NONFATAL,
"cannot specify 64-bit segment on processor below an x86-64");
i = 16;
diff --git a/ndisasm.c b/ndisasm.c
index 638299ff..3212629f 100644
--- a/ndisasm.c
+++ b/ndisasm.c
@@ -88,7 +88,7 @@ int main(int argc, char **argv)
bool autosync = false;
int bits = 16, b;
bool eof = false;
- iflags_t prefer = 0;
+ iflag_t prefer;
bool rn_error;
int32_t offset;
FILE *fp;
@@ -96,6 +96,7 @@ int main(int argc, char **argv)
tolower_init();
nasm_set_verror(ndisasm_verror);
nasm_init_malloc_error();
+ iflag_clear_all(&prefer);
offset = 0;
init_sync();
@@ -229,14 +230,20 @@ int main(int argc, char **argv)
return 1;
}
if (!strcmp(v, "intel")) {
- prefer = 0; /* Default */
+ iflag_clear_all(&prefer); /* default */
} else if (!strcmp(v, "amd")) {
- prefer = IF_AMD | IF_3DNOW;
+ iflag_clear_all(&prefer);
+ iflag_set(&prefer, IF_AMD);
+ iflag_set(&prefer, IF_3DNOW);
} else if (!strcmp(v, "cyrix")) {
- prefer = IF_CYRIX | IF_3DNOW;
- } else if (!strcmp(v, "idt") || !strcmp(v, "centaur")
- || !strcmp(v, "winchip")) {
- prefer = IF_3DNOW;
+ iflag_clear_all(&prefer);
+ iflag_set(&prefer, IF_CYRIX);
+ iflag_set(&prefer, IF_3DNOW);
+ } else if (!strcmp(v, "idt") ||
+ !strcmp(v, "centaur") ||
+ !strcmp(v, "winchip")) {
+ iflag_clear_all(&prefer);
+ iflag_set(&prefer, IF_3DNOW);
} else {
fprintf(stderr,
"%s: unknown vendor `%s' specified with `-p'\n",
@@ -311,7 +318,7 @@ int main(int argc, char **argv)
while (p > q && (p - q >= INSN_MAX || lenread == 0)) {
lendis =
disasm((uint8_t *) q, outbuf, sizeof(outbuf), bits,
- offset, autosync, prefer);
+ offset, autosync, &prefer);
if (!lendis || lendis > (p - q)
|| ((nextsync || synclen) &&
(uint32_t)lendis > nextsync - offset))