iflag: Start using new instruction flags engine
authorCyrill Gorcunov <gorcunov@gmail.com>
Sat, 9 Nov 2013 18:16:11 +0000 (22:16 +0400)
committerCyrill Gorcunov <gorcunov@gmail.com>
Sun, 24 Nov 2013 09:20:59 +0000 (13:20 +0400)
Here we start using instruction flags generator.

Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
13 files changed:
Makefile.in
Mkfiles/msvc.mak
Mkfiles/netware.mak
Mkfiles/openwcom.mak
Mkfiles/owlinux.mak
assemble.c
assemble.h
disasm.c
disasm.h
insns.h
insns.pl
nasm.c
ndisasm.c

index e4c56b5..c3dbc0f 100644 (file)
@@ -89,10 +89,13 @@ NASM =      nasm.$(O) nasmlib.$(O) ver.$(O) \
        strfunc.$(O) tokhash.$(O) regvals.$(O) regflags.$(O) \
        ilog2.$(O) \
        lib/strlcpy.$(O) \
-       preproc-nop.$(O) disp8.$(O)
+       preproc-nop.$(O) \
+       disp8.$(O) \
+       iflag.$(O)
 
 NDISASM = ndisasm.$(O) disasm.$(O) sync.$(O) nasmlib.$(O) ver.$(O) \
-       insnsd.$(O) insnsb.$(O) insnsn.$(O) regs.$(O) regdis.$(O) disp8.$(O)
+       insnsd.$(O) insnsb.$(O) insnsn.$(O) regs.$(O) regdis.$(O) \
+       disp8.$(O) iflag.$(O)
 #-- End File Lists --#
 
 all: nasm$(X) ndisasm$(X) manpages rdf
@@ -108,6 +111,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 +192,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
index a96bd15..e93219f 100644 (file)
@@ -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:
index 178dbdc..8615431 100644 (file)
@@ -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)
index 8a0ffef..222163d 100644 (file)
@@ -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
index d04c80d..04fb90a 100644 (file)
@@ -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:
index 0667ef7..193c487 100644 (file)
@@ -218,7 +218,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;
@@ -390,7 +390,7 @@ static bool jmp_match(int32_t segment, int64_t offset, int bits,
     return is_byte;
 }
 
-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)
 {
@@ -704,7 +704,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;
@@ -1231,7 +1231,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
                  * only for mib operands, make a single reg index [reg*1].
                  * gas uses this form to explicitly denote index register.
                  */
-                if ((temp->flags & IF_MIB) &&
+                if (itemp_has(temp, IF_MIB) &&
                     (opy->indexreg == -1 && opy->hintbase == opy->basereg &&
                      opy->hinttype == EAH_NOTBASE)) {
                     opy->indexreg = opy->basereg;
@@ -1310,7 +1310,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 */
@@ -1322,7 +1322,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");
     }
@@ -2003,8 +2003,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...
              */
@@ -2090,7 +2089,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;
 
     /*
@@ -2103,29 +2102,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;
@@ -2146,9 +2145,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 {
@@ -2235,10 +2234,10 @@ 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;
         } else if (instruction->prefixes[PPS_EVEX] &&
-                   !(itemp->flags & IF_AVX512)) {
+                   !itemp_has(itemp, IF_AVX512)) {
             return MERR_ENCMISMATCH;
         }
     }
@@ -2249,8 +2248,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) {
@@ -2272,19 +2271,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;
@@ -2298,7 +2297,7 @@ static enum match_result matches(const struct itemplate *itemp,
     /*
      * Check if BND prefix is allowed
      */
-    if ((IF_BND & ~itemp->flags) &&
+    if (!itemp_has(itemp, IF_BND) &&
         has_prefix(instruction, PPS_REP, P_BND))
         return MERR_BADBND;
 
index 1197d59..381e3ab 100644 (file)
 #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
index 9064b65..b7c5027 100644 (file)
--- a/disasm.c
+++ b/disasm.c
@@ -501,11 +501,11 @@ 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)
-        drep = (t->flags & IF_BND ? P_BND : P_REPNE);
+        drep = (itemp_has(t, IF_BND) ? P_BND : P_REPNE);
     else if (prefix->rep == 0xF3)
         drep = P_REP;
 
@@ -1099,7 +1099,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;
@@ -1110,7 +1110,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, flags;
+    iflag_t goodness, best;
     int best_pref;
     struct prefix_info prefix;
     bool end_prefix;
@@ -1277,7 +1277,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;
 
@@ -1331,13 +1331,14 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
              */
             if (works) {
                 int i, nprefix;
-                goodness = ((*p)->flags & IF_PFMASK) ^ prefer;
-                nprefix = 0;
-                for (i = 0; i < MAXPREFIX; i++)
-                    if (tmp_ins.prefixes[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;
@@ -1355,7 +1356,6 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
     /* Pick the best match */
     p = best_p;
     length = best_length;
-    flags = (*p)->flags;
 
     slen = 0;
 
@@ -1528,7 +1528,7 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
                         nasm_reg_names[(o->basereg-EXPR_REG_START)]);
                 started = true;
             }
-            if (o->indexreg != -1 && !(flags & IF_MIB)) {
+            if (o->indexreg != -1 && !itemp_has(*best_p, IF_MIB)) {
                 if (started)
                     output[slen++] = '+';
                 slen += snprintf(output + slen, outbufsize - slen, "%s",
@@ -1607,7 +1607,7 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
                 }
             }
 
-            if (o->indexreg != -1 && (flags & IF_MIB)) {
+            if (o->indexreg != -1 && itemp_has(*best_p, IF_MIB)) {
                 output[slen++] = ',';
                 slen += snprintf(output + slen, outbufsize - slen, "%s",
                         nasm_reg_names[(o->indexreg-EXPR_REG_START)]);
index 70a9a7b..fa6e2e2 100644 (file)
--- a/disasm.h
+++ b/disasm.h
 #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 dd447c5..8f04d13 100644 (file)
--- 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 */
@@ -47,119 +48,4 @@ 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.
- */
-
-#define IF_SM           UINT64_C(0x00000001)    /* size match */
-#define IF_SM2          UINT64_C(0x00000002)    /* size match first two operands */
-#define IF_SB           UINT64_C(0x00000004)    /* unsized operands can't be non-byte */
-#define IF_SW           UINT64_C(0x00000008)    /* unsized operands can't be non-word */
-#define IF_SD           UINT64_C(0x0000000C)    /* unsized operands can't be non-dword */
-#define IF_SQ           UINT64_C(0x00000010)    /* unsized operands can't be non-qword */
-#define IF_SO           UINT64_C(0x00000014)    /* unsized operands can't be non-oword */
-#define IF_SY           UINT64_C(0x00000018)    /* unsized operands can't be non-yword */
-#define IF_SZ           UINT64_C(0x0000001C)    /* unsized operands can't be non-zword */
-#define IF_SIZE         UINT64_C(0x00000038)    /* unsized operands must match the bitsize */
-#define IF_SX           UINT64_C(0x0000003C)    /* unsized operands not allowed */
-#define IF_SMASK        UINT64_C(0x0000003C)    /* mask for unsized argument size */
-#define IF_AR0          UINT64_C(0x00000040)    /* SB, SW, SD applies to argument 0 */
-#define IF_AR1          UINT64_C(0x00000080)    /* SB, SW, SD applies to argument 1 */
-#define IF_AR2          UINT64_C(0x000000C0)    /* SB, SW, SD applies to argument 2 */
-#define IF_AR3          UINT64_C(0x00000100)    /* SB, SW, SD applies to argument 3 */
-#define IF_AR4          UINT64_C(0x00000140)    /* SB, SW, SD applies to argument 4 */
-#define IF_ARMASK       UINT64_C(0x000001C0)    /* mask for unsized argument spec */
-#define IF_ARSHFT       6                         /* LSB in IF_ARMASK */
-#define IF_OPT          UINT64_C(0x00000200)    /* optimizing assembly only */
-/* The next 3 bits aren't actually used for anything */
-#define IF_PRIV         UINT64_C(0x00000000)    /* it's a privileged instruction */
-#define IF_SMM          UINT64_C(0x00000000)    /* it's only valid in SMM */
-#define IF_PROT         UINT64_C(0x00000000)    /* it's protected mode only */
-#define IF_LOCK         UINT64_C(0x00000400)    /* lockable if operand 0 is memory */
-#define IF_NOLONG       UINT64_C(0x00000800)    /* it's not available in long mode */
-#define IF_LONG         UINT64_C(0x00001000)    /* long mode instruction */
-#define IF_NOHLE        UINT64_C(0x00002000)    /* HLE prefixes forbidden */
-#define IF_MIB          UINT64_C(0x00004000)    /* Disassemble with split EA */
-#define IF_BND          UINT64_C(0x00008000)    /* BND (0xF2) prefix available */
-/* These flags are currently not used for anything - intended for insn set */
-#define IF_UNDOC        UINT64_C(0x8000000000)    /* it's an undocumented instruction */
-#define IF_HLE          UINT64_C(0x4000000000)    /* HACK NEED TO REORGANIZE THESE BITS */
-#define IF_AVX512       UINT64_C(0x2000000000)    /* it's an AVX-512F (512b) instruction */
-#define IF_FPU          UINT64_C(0x0100000000)    /* it's an FPU instruction */
-#define IF_MMX          UINT64_C(0x0200000000)    /* it's an MMX instruction */
-#define IF_3DNOW        UINT64_C(0x0300000000)    /* it's a 3DNow! instruction */
-#define IF_SSE          UINT64_C(0x0400000000)    /* it's a SSE (KNI, MMX2) instruction */
-#define IF_SSE2         UINT64_C(0x0500000000)    /* it's a SSE2 instruction */
-#define IF_SSE3         UINT64_C(0x0600000000)    /* it's a SSE3 (PNI) instruction */
-#define IF_VMX          UINT64_C(0x0700000000)    /* it's a VMX instruction */
-#define IF_SSSE3        UINT64_C(0x0800000000)    /* it's an SSSE3 instruction */
-#define IF_SSE4A        UINT64_C(0x0900000000)    /* AMD SSE4a */
-#define IF_SSE41        UINT64_C(0x0A00000000)    /* it's an SSE4.1 instruction */
-#define IF_SSE42        UINT64_C(0x0B00000000)    /* HACK NEED TO REORGANIZE THESE BITS */
-#define IF_SSE5         UINT64_C(0x0C00000000)    /* HACK NEED TO REORGANIZE THESE BITS */
-#define IF_AVX          UINT64_C(0x0D00000000)    /* it's an AVX     (128b) instruction */
-#define IF_AVX2         UINT64_C(0x0E00000000)    /* it's an AVX2    (256b) instruction */
-#define IF_FMA          UINT64_C(0x1000000000)    /* HACK NEED TO REORGANIZE THESE BITS */
-#define IF_BMI1         UINT64_C(0x1100000000)    /* HACK NEED TO REORGANIZE THESE BITS */
-#define IF_BMI2         UINT64_C(0x1200000000)    /* HACK NEED TO REORGANIZE THESE BITS */
-#define IF_TBM          UINT64_C(0x1300000000)    /* HACK NEED TO REORGANIZE THESE BITS */
-#define IF_RTM          UINT64_C(0x1400000000)    /* HACK NEED TO REORGANIZE THESE BITS */
-#define IF_INVPCID      UINT64_C(0x1500000000)    /* HACK NEED TO REORGANIZE THESE BITS */
-#define IF_AVX512CD     (UINT64_C(0x1600000000)|IF_AVX512) /* AVX-512 Conflict Detection insns */
-#define IF_AVX512ER     (UINT64_C(0x1700000000)|IF_AVX512) /* AVX-512 Exponential and Reciprocal */
-#define IF_AVX512PF     (UINT64_C(0x1800000000)|IF_AVX512) /* AVX-512 Prefetch instructions */
-#define IF_MPX          UINT64_C(0x1900000000)    /* MPX instructions */
-#define IF_SHA          UINT64_C(0x1A00000000)    /* SHA instructions */
-#define IF_PREFETCHWT1  UINT64_C(0x1F00000000)    /* PREFETCHWT1 instructions */
-#define IF_INSMASK      UINT64_C(0xFF00000000)    /* the mask for instruction set types */
-#define IF_PMASK        UINT64_C(0xFF000000)    /* the mask for processor types */
-#define IF_PLEVEL       UINT64_C(0x0F000000)    /* the mask for processor instr. level */
-                                                  /* also the highest possible processor */
-#define IF_8086         UINT64_C(0x00000000)    /* 8086 instruction */
-#define IF_186          UINT64_C(0x01000000)    /* 186+ instruction */
-#define IF_286          UINT64_C(0x02000000)    /* 286+ instruction */
-#define IF_386          UINT64_C(0x03000000)    /* 386+ instruction */
-#define IF_486          UINT64_C(0x04000000)    /* 486+ instruction */
-#define IF_PENT         UINT64_C(0x05000000)    /* Pentium instruction */
-#define IF_P6           UINT64_C(0x06000000)    /* P6 instruction */
-#define IF_KATMAI       UINT64_C(0x07000000)    /* Katmai instructions */
-#define IF_WILLAMETTE   UINT64_C(0x08000000)    /* Willamette instructions */
-#define IF_PRESCOTT     UINT64_C(0x09000000)    /* Prescott instructions */
-#define IF_X86_64       UINT64_C(0x0A000000)    /* x86-64 instruction (long or legacy mode) */
-#define IF_NEHALEM      UINT64_C(0x0B000000)    /* Nehalem instruction */
-#define IF_WESTMERE     UINT64_C(0x0C000000)    /* Westmere instruction */
-#define IF_SANDYBRIDGE  UINT64_C(0x0D000000)    /* Sandy Bridge instruction */
-#define IF_FUTURE       UINT64_C(0x0E000000)    /* Future processor (not yet disclosed) */
-#define IF_X64          (IF_LONG|IF_X86_64)
-#define IF_IA64         UINT64_C(0x0F000000)    /* IA64 instructions (in x86 mode) */
-#define IF_CYRIX        UINT64_C(0x10000000)    /* Cyrix-specific instruction */
-#define IF_AMD          UINT64_C(0x20000000)    /* AMD-specific instruction */
-#define IF_SPMASK       UINT64_C(0x30000000)    /* specific processor types mask */
-#define IF_PFMASK       (IF_INSMASK|IF_SPMASK) /* disassembly "prefer" mask */
-
 #endif /* NASM_INSNS_H */
index 8bd76ab..bf91469 100755 (executable)
--- 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 3a0c050..b83810d 100644 (file)
--- 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;
index 638299f..3212629 100644 (file)
--- 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))