]> granicus.if.org Git - yasm/commitdiff
Restructure x86 CPU handling to allow for more than 30 CPU feature flags.
authorPeter Johnson <peter@tortall.net>
Wed, 12 Sep 2007 06:55:51 +0000 (06:55 -0000)
committerPeter Johnson <peter@tortall.net>
Wed, 12 Sep 2007 06:55:51 +0000 (06:55 -0000)
svn path=/trunk/yasm/; revision=1945

modules/arch/x86/gen_x86_insn.py
modules/arch/x86/x86arch.c
modules/arch/x86/x86arch.h
modules/arch/x86/x86cpu.gperf
modules/arch/x86/x86id.c

index f862f8ed776eafaec78fe4a736b4334fb1ce1c31..412659676f3488e10d35011a13a1b3fb90a82d0c 100755 (executable)
@@ -256,6 +256,17 @@ class GroupForm(object):
         if len(self.modifiers) > 3:
             raise ValueError("too many modifiers: %s" % (self.modifiers,))
 
+        cpus_str = []
+        if self.cpu is not None:
+            if len(self.cpu) > 3:
+                raise ValueError("too many CPUs: %s" % (self.cpu,))
+
+            # Ensure CPUs initializer string is at least 3 long
+            cpus_str.extend("CPU_%s" % x for x in sorted(self.cpu))
+
+        # Ensure cpus initializer string is 3 long; 0=CPU_Any
+        cpus_str.extend(["0", "0", "0"])
+
         # Number gap elements as we copy
         modnames = []
         n = 0
@@ -283,7 +294,9 @@ class GroupForm(object):
         mod_str = "|".join("MOD_%s" % x for x in mods)
 
         # Build instruction info structure initializer
-        return "{ "+ ", ".join([cpus_str or "CPU_Any",
+        return "{ "+ ", ".join([cpus_str[0],
+                                cpus_str[1],
+                                cpus_str[2],
                                 mod_str or "0",
                                 "%d" % (self.opersize or 0),
                                 "%d" % (self.def_opersize_64 or 0),
@@ -366,10 +379,16 @@ class Insn(object):
         else:
             suffix_str = self.suffix
 
-        if self.cpu is None:
-            cpu_str = ""
-        else:
-            cpu_str = "|".join("CPU_%s" % x for x in sorted(self.cpu))
+        cpus_str = []
+        if self.cpu is not None:
+            if len(self.cpu) > 3:
+                raise ValueError("too many CPUs: %s" % (self.cpu,))
+
+            # Ensure CPUs initializer string is at least 3 long
+            cpus_str.extend("CPU_%s" % x for x in sorted(self.cpu))
+
+        # Ensure cpus initializer string is 3 long
+        cpus_str.extend(["0", "0", "0"])
 
         if len(self.modifiers) > 3:
             raise ValueError("too many modifiers")
@@ -408,8 +427,10 @@ class Insn(object):
         return ",\t".join(["%s_insn" % self.groupname,
                            "(%sUL<<8)|%d" % \
                                 (modifier_str, len(groups[self.groupname])),
-                           cpu_str or "CPU_Any",
-                           suffix_str])
+                           suffix_str,
+                           cpus_str[0],
+                           cpus_str[1],
+                           cpus_str[2]])
 
 insns = {}
 def add_insn(name, groupname, **kwargs):
@@ -426,7 +447,9 @@ class Prefix(object):
         return ",\t".join(["NULL",
                            "X86_" + self.groupname,
                            "0x%02X" % self.value,
-                           "NONE"])
+                           self.only64 and "CPU_64" or "0",
+                           "0",
+                           "0"])
 
 gas_insns = {}
 nasm_insns = {}
@@ -537,6 +560,16 @@ def output_groups(f):
 # General instruction groupings
 #####################################################################
 
+#
+# Empty instruction
+#
+add_group("empty", opcode=[], operands=[])
+
+#
+# Placeholder for instructions invalid in 64-bit mode
+#
+add_group("not64", opcode=[], operands=[], not64=True)
+
 #
 # One byte opcode instructions with no operands
 #
index 0f8c9527770cc3bdace822c91d1300cdb60d4800..d410ac0e1986069453346f58add00feb83379a59 100644 (file)
@@ -57,7 +57,13 @@ x86_create(const char *machine, const char *parser,
 
     arch_x86->arch.module = &yasm_x86_LTX_arch;
 
-    arch_x86->cpu_enabled = ~CPU_Any;
+    /* default to all instructions/features enabled */
+    arch_x86->active_cpu = 0;
+    arch_x86->cpu_enables_size = 1;
+    arch_x86->cpu_enables = yasm_xmalloc(sizeof(wordptr));
+    arch_x86->cpu_enables[0] = BitVector_Create(64, FALSE);
+    BitVector_Fill(arch_x86->cpu_enables[0]);
+
     arch_x86->amd64_machine = amd64_machine;
     arch_x86->mode_bits = 0;
     arch_x86->force_strict = 0;
@@ -79,6 +85,11 @@ x86_create(const char *machine, const char *parser,
 static void
 x86_destroy(/*@only@*/ yasm_arch *arch)
 {
+    yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
+    unsigned int i;
+    for (i=0; i<arch_x86->cpu_enables_size; i++)
+        BitVector_Destroy(arch_x86->cpu_enables[i]);
+    yasm_xfree(arch_x86->cpu_enables);
     yasm_xfree(arch);
 }
 
index cbe26f48541b29aa88df5943a4bca1272f4ab68b..efd8e74f906104f2ece67451087c02d218a2ae5e 100644 (file)
 #ifndef YASM_X86ARCH_H
 #define YASM_X86ARCH_H
 
+#include <libyasm/bitvect.h>
+
 /* Available CPU feature flags */
-#define CPU_Any     (0UL)       /* Any old cpu will do */
+#define CPU_Any     0       /* Any old cpu will do */
 #define CPU_086     CPU_Any
-#define CPU_186     (1UL<<0)    /* i186 or better required */
-#define CPU_286     (1UL<<1)    /* i286 or better required */
-#define CPU_386     (1UL<<2)    /* i386 or better required */
-#define CPU_486     (1UL<<3)    /* i486 or better required */
-#define CPU_586     (1UL<<4)    /* i585 or better required */
-#define CPU_686     (1UL<<5)    /* i686 or better required */
-#define CPU_P3      (1UL<<6)    /* Pentium3 or better required */
-#define CPU_P4      (1UL<<7)    /* Pentium4 or better required */
-#define CPU_IA64    (1UL<<8)    /* IA-64 or better required */
-#define CPU_K6      (1UL<<9)    /* AMD K6 or better required */
-#define CPU_Athlon  (1UL<<10)   /* AMD Athlon or better required */
-#define CPU_Hammer  (1UL<<11)   /* AMD Sledgehammer or better required */
-#define CPU_FPU     (1UL<<12)   /* FPU support required */
-#define CPU_MMX     (1UL<<13)   /* MMX support required */
-#define CPU_SSE     (1UL<<14)   /* Streaming SIMD extensions required */
-#define CPU_SSE2    (1UL<<15)   /* Streaming SIMD extensions 2 required */
-#define CPU_SSE3    (1UL<<16)   /* Streaming SIMD extensions 3 required */
-#define CPU_3DNow   (1UL<<17)   /* 3DNow! support required */
-#define CPU_Cyrix   (1UL<<18)   /* Cyrix-specific instruction */
-#define CPU_AMD     (1UL<<19)   /* AMD-specific inst. (older than K6) */
-#define CPU_SMM     (1UL<<20)   /* System Management Mode instruction */
-#define CPU_Prot    (1UL<<21)   /* Protected mode only instruction */
-#define CPU_Undoc   (1UL<<22)   /* Undocumented instruction */
-#define CPU_Obs     (1UL<<23)   /* Obsolete instruction */
-#define CPU_Priv    (1UL<<24)   /* Priveleged instruction */
-#define CPU_SVM     (1UL<<25)   /* Secure Virtual Machine instruction */
-#define CPU_PadLock (1UL<<25)   /* VIA PadLock instruction */
-#define CPU_EM64T   (1UL<<26)   /* Intel EM64T or better */
-#define CPU_SSSE3   (1UL<<27)   /* Streaming SIMD extensions 3 required */
-#define CPU_SSE41   (1UL<<28)   /* Streaming SIMD extensions 4.1 required */
-#define CPU_SSE42   (1UL<<29)   /* Streaming SIMD extensions 4.2 required */
-#define CPU_SSE4    (CPU_SSE41|CPU_SSE42)
+#define CPU_186     1       /* i186 or better required */
+#define CPU_286     2       /* i286 or better required */
+#define CPU_386     3       /* i386 or better required */
+#define CPU_486     4       /* i486 or better required */
+#define CPU_586     5       /* i585 or better required */
+#define CPU_686     6       /* i686 or better required */
+#define CPU_P3      7       /* Pentium3 or better required */
+#define CPU_P4      8       /* Pentium4 or better required */
+#define CPU_IA64    9       /* IA-64 or better required */
+#define CPU_K6      10      /* AMD K6 or better required */
+#define CPU_Athlon  11      /* AMD Athlon or better required */
+#define CPU_Hammer  12      /* AMD Sledgehammer or better required */
+#define CPU_FPU     13      /* FPU support required */
+#define CPU_MMX     14      /* MMX support required */
+#define CPU_SSE     15      /* Streaming SIMD extensions required */
+#define CPU_SSE2    16      /* Streaming SIMD extensions 2 required */
+#define CPU_SSE3    17      /* Streaming SIMD extensions 3 required */
+#define CPU_3DNow   18      /* 3DNow! support required */
+#define CPU_Cyrix   19      /* Cyrix-specific instruction */
+#define CPU_AMD     20      /* AMD-specific inst. (older than K6) */
+#define CPU_SMM     21      /* System Management Mode instruction */
+#define CPU_Prot    22      /* Protected mode only instruction */
+#define CPU_Undoc   23      /* Undocumented instruction */
+#define CPU_Obs     24      /* Obsolete instruction */
+#define CPU_Priv    25      /* Priveleged instruction */
+#define CPU_SVM     26      /* Secure Virtual Machine instruction */
+#define CPU_PadLock 27      /* VIA PadLock instruction */
+#define CPU_EM64T   28      /* Intel EM64T or better */
+#define CPU_SSSE3   29      /* Streaming SIMD extensions 3 required */
+#define CPU_SSE41   30      /* Streaming SIMD extensions 4.1 required */
+#define CPU_SSE42   31      /* Streaming SIMD extensions 4.2 required */
 
 /* Technically not CPU capabilities, they do affect what instructions are
  * available.  These are tested against BITS==64.
  */
-#define CPU_64      (1UL<<30)   /* Only available in 64-bit mode */
-#define CPU_Not64   (1UL<<31)   /* Not available (invalid) in 64-bit mode */
+#define CPU_64      120     /* Only available in 64-bit mode */
+#define CPU_Not64   121     /* Not available (invalid) in 64-bit mode */
 
 typedef struct yasm_arch_x86 {
     yasm_arch_base arch;        /* base structure */
 
     /* What instructions/features are enabled? */
-    unsigned long cpu_enabled;
+    unsigned int active_cpu;        /* active index into cpu_enables table */
+    unsigned int cpu_enables_size;  /* size of cpu_enables table */
+    wordptr *cpu_enables;
+
     unsigned int amd64_machine;
     enum {
         X86_PARSER_NASM = 0,
index 84f4d9fb278ff79c406f7b829bc24dcd5bbb0ccf..1feae1db7ab4b6d6b86f4082a9f993f00fd2006e 100644 (file)
@@ -32,58 +32,153 @@ RCSID("$Id$");
 
 #include "modules/arch/x86/x86arch.h"
 
-enum cpu_mode {
-    CPU_MODE_VERBATIM = 1,
-    CPU_MODE_SET,
-    CPU_MODE_CLEAR
-};
+#define PROC_8086      0
+#define PROC_186       1
+#define PROC_286       2
+#define PROC_386       3
+#define PROC_486       4
+#define PROC_586       5
+#define PROC_686       6
+#define PROC_p2                7
+#define PROC_p3                8
+#define PROC_p4                9
+#define PROC_prescott  10
+#define PROC_conroe    11
+#define PROC_penryn    12
+#define PROC_nehalem   13
+
+static void
+x86_cpu_intel(wordptr cpu, unsigned int data)
+{
+    BitVector_Empty(cpu);
+
+    BitVector_Bit_On(cpu, CPU_Priv);
+    if (data >= PROC_286)
+        BitVector_Bit_On(cpu, CPU_Prot);
+    if (data >= PROC_386)
+        BitVector_Bit_On(cpu, CPU_SMM);
+    if (data >= PROC_nehalem)
+        BitVector_Bit_On(cpu, CPU_SSE42);
+    if (data >= PROC_penryn)
+        BitVector_Bit_On(cpu, CPU_SSE41);
+    if (data >= PROC_conroe)
+        BitVector_Bit_On(cpu, CPU_SSSE3);
+    if (data >= PROC_prescott)
+        BitVector_Bit_On(cpu, CPU_SSE3);
+    if (data >= PROC_p4)
+        BitVector_Bit_On(cpu, CPU_SSE2);
+    if (data >= PROC_p3)
+        BitVector_Bit_On(cpu, CPU_SSE);
+    if (data >= PROC_p2)
+        BitVector_Bit_On(cpu, CPU_MMX);
+    if (data >= PROC_486)
+        BitVector_Bit_On(cpu, CPU_FPU);
+    if (data >= PROC_prescott)
+        BitVector_Bit_On(cpu, CPU_EM64T);
+
+    if (data >= PROC_p4)
+        BitVector_Bit_On(cpu, CPU_P4);
+    if (data >= PROC_p3)
+        BitVector_Bit_On(cpu, CPU_P3);
+    if (data >= PROC_686)
+        BitVector_Bit_On(cpu, CPU_686);
+    if (data >= PROC_586)
+        BitVector_Bit_On(cpu, CPU_586);
+    if (data >= PROC_486)
+        BitVector_Bit_On(cpu, CPU_486);
+    if (data >= PROC_386)
+        BitVector_Bit_On(cpu, CPU_386);
+    if (data >= PROC_286)
+        BitVector_Bit_On(cpu, CPU_286);
+    if (data >= PROC_186)
+        BitVector_Bit_On(cpu, CPU_186);
+    BitVector_Bit_On(cpu, CPU_086);
+}
+
+static void
+x86_cpu_ia64(wordptr cpu, unsigned int data)
+{
+    BitVector_Empty(cpu);
+    BitVector_Bit_On(cpu, CPU_Priv);
+    BitVector_Bit_On(cpu, CPU_Prot);
+    BitVector_Bit_On(cpu, CPU_SMM);
+    BitVector_Bit_On(cpu, CPU_SSE2);
+    BitVector_Bit_On(cpu, CPU_SSE);
+    BitVector_Bit_On(cpu, CPU_MMX);
+    BitVector_Bit_On(cpu, CPU_FPU);
+    BitVector_Bit_On(cpu, CPU_IA64);
+    BitVector_Bit_On(cpu, CPU_P4);
+    BitVector_Bit_On(cpu, CPU_P3);
+    BitVector_Bit_On(cpu, CPU_686);
+    BitVector_Bit_On(cpu, CPU_586);
+    BitVector_Bit_On(cpu, CPU_486);
+    BitVector_Bit_On(cpu, CPU_386);
+    BitVector_Bit_On(cpu, CPU_286);
+    BitVector_Bit_On(cpu, CPU_186);
+    BitVector_Bit_On(cpu, CPU_086);
+}
+
+#define PROC_hammer 8
+#define PROC_k7     7
+#define PROC_k6     6
+
+static void
+x86_cpu_amd(wordptr cpu, unsigned int data)
+{
+    BitVector_Empty(cpu);
+
+    BitVector_Bit_On(cpu, CPU_Priv);
+    BitVector_Bit_On(cpu, CPU_Prot);
+    BitVector_Bit_On(cpu, CPU_SMM);
+    BitVector_Bit_On(cpu, CPU_3DNow);
+    if (data >= PROC_hammer)
+        BitVector_Bit_On(cpu, CPU_SSE2);
+    if (data >= PROC_k7)
+        BitVector_Bit_On(cpu, CPU_SSE);
+    if (data >= PROC_k6)
+        BitVector_Bit_On(cpu, CPU_MMX);
+    BitVector_Bit_On(cpu, CPU_FPU);
+
+    if (data >= PROC_hammer)
+        BitVector_Bit_On(cpu, CPU_Hammer);
+    if (data >= PROC_k7)
+        BitVector_Bit_On(cpu, CPU_Athlon);
+    if (data >= PROC_k6)
+        BitVector_Bit_On(cpu, CPU_K6);
+    BitVector_Bit_On(cpu, CPU_686);
+    BitVector_Bit_On(cpu, CPU_586);
+    BitVector_Bit_On(cpu, CPU_486);
+    BitVector_Bit_On(cpu, CPU_386);
+    BitVector_Bit_On(cpu, CPU_286);
+    BitVector_Bit_On(cpu, CPU_186);
+    BitVector_Bit_On(cpu, CPU_086);
+}
+
+static void
+x86_cpu_set(wordptr cpu, unsigned int data)
+{
+    BitVector_Bit_On(cpu, data);
+}
+
+static void
+x86_cpu_clear(wordptr cpu, unsigned int data)
+{
+    BitVector_Bit_Off(cpu, data);
+}
 
-#define PROC_186       CPU_186|CPU_Priv
-#define PROC_286       CPU_186|CPU_286|CPU_Priv
-#define PROC_386       CPU_186|CPU_286|CPU_386|CPU_SMM|CPU_Prot|CPU_Priv
-#define PROC_486       CPU_186|CPU_286|CPU_386|CPU_486|CPU_FPU|CPU_SMM|\
-                       CPU_Prot|CPU_Priv
-#define PROC_586       CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_FPU|\
-                       CPU_SMM|CPU_Prot|CPU_Priv
-#define PROC_686       CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
-                       CPU_FPU|CPU_SMM|CPU_Prot|CPU_Priv
-#define PROC_p2                CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
-                       CPU_FPU|CPU_MMX|CPU_SMM|CPU_Prot|CPU_Priv
-#define PROC_p3                CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
-                       CPU_P3|CPU_FPU|CPU_MMX|CPU_SSE|CPU_SMM|CPU_Prot|\
-                       CPU_Priv
-#define PROC_p4                CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
-                       CPU_P3|CPU_P4|CPU_FPU|CPU_MMX|CPU_SSE|CPU_SSE2|\
-                       CPU_SMM|CPU_Prot|CPU_Priv
-#define PROC_ia64      CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
-                       CPU_P3|CPU_P4|CPU_IA64|CPU_FPU|CPU_MMX|CPU_SSE|\
-                       CPU_SSE2|CPU_SMM|CPU_Prot|CPU_Priv
-#define PROC_k6                CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
-                       CPU_K6|CPU_FPU|CPU_MMX|CPU_3DNow|CPU_SMM|CPU_Prot|\
-                       CPU_Priv
-#define PROC_k7                CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
-                       CPU_K6|CPU_Athlon|CPU_FPU|CPU_MMX|CPU_SSE|CPU_3DNow|\
-                       CPU_SMM|CPU_Prot|CPU_Priv
-#define PROC_hammer    CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
-                       CPU_K6|CPU_Athlon|CPU_Hammer|CPU_FPU|CPU_MMX|\
-                       CPU_SSE|CPU_SSE2|CPU_3DNow|CPU_SMM|CPU_Prot|\
-                       CPU_Priv
-#define PROC_prescott  CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
-                       CPU_Hammer|CPU_EM64T|CPU_FPU|CPU_MMX|\
-                       CPU_SSE|CPU_SSE2|CPU_SSE3|CPU_SMM|\
-                       CPU_Prot|CPU_Priv
-#define PROC_conroe    CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
-                       CPU_Hammer|CPU_EM64T|CPU_FPU|CPU_MMX|\
-                       CPU_SSE|CPU_SSE2|CPU_SSE3|CPU_SSSE3|CPU_SMM|\
-                       CPU_Prot|CPU_Priv
-#define PROC_penryn    CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
-                       CPU_Hammer|CPU_EM64T|CPU_FPU|CPU_MMX|\
-                       CPU_SSE|CPU_SSE2|CPU_SSE3|CPU_SSSE3|CPU_SSE41|CPU_SMM|\
-                       CPU_Prot|CPU_Priv
-#define PROC_nehalem   CPU_186|CPU_286|CPU_386|CPU_486|CPU_586|CPU_686|\
-                       CPU_Hammer|CPU_EM64T|CPU_FPU|CPU_MMX|\
-                       CPU_SSE|CPU_SSE2|CPU_SSE3|CPU_SSSE3|CPU_SSE41|\
-                       CPU_SSE42|CPU_SMM|CPU_Prot|CPU_Priv
+static void
+x86_cpu_set_sse4(wordptr cpu, unsigned int data)
+{
+    BitVector_Bit_On(cpu, CPU_SSE41);
+    BitVector_Bit_On(cpu, CPU_SSE42);
+}
+
+static void
+x86_cpu_clear_sse4(wordptr cpu, unsigned int data)
+{
+    BitVector_Bit_Off(cpu, CPU_SSE41);
+    BitVector_Bit_Off(cpu, CPU_SSE42);
+}
 
 %}
 %ignore-case
@@ -96,118 +191,118 @@ enum cpu_mode {
 %define lookup-function-name cpu_find
 struct cpu_parse_data {
     const char *name;
-    enum cpu_mode mode;
-    unsigned long cpu;
+    void (*handler) (wordptr cpu, unsigned int data);
+    unsigned int data;
 };
 %%
-8086,          CPU_MODE_VERBATIM,      CPU_Priv
-186,           CPU_MODE_VERBATIM,      PROC_186
-80186,         CPU_MODE_VERBATIM,      PROC_186
-i186,          CPU_MODE_VERBATIM,      PROC_186
-286,           CPU_MODE_VERBATIM,      PROC_286
-80286,         CPU_MODE_VERBATIM,      PROC_286
-i286,          CPU_MODE_VERBATIM,      PROC_286
-386,           CPU_MODE_VERBATIM,      PROC_386
-80386,         CPU_MODE_VERBATIM,      PROC_386
-i386,          CPU_MODE_VERBATIM,      PROC_386
-486,           CPU_MODE_VERBATIM,      PROC_486
-80486,         CPU_MODE_VERBATIM,      PROC_486
-i486,          CPU_MODE_VERBATIM,      PROC_486
-586,           CPU_MODE_VERBATIM,      PROC_586
-i586,          CPU_MODE_VERBATIM,      PROC_586
-pentium,       CPU_MODE_VERBATIM,      PROC_586
-p5,            CPU_MODE_VERBATIM,      PROC_586
-686,           CPU_MODE_VERBATIM,      PROC_686
-i686,          CPU_MODE_VERBATIM,      PROC_686
-p6,            CPU_MODE_VERBATIM,      PROC_686
-ppro,          CPU_MODE_VERBATIM,      PROC_686
-pentiumpro,    CPU_MODE_VERBATIM,      PROC_686
-p2,            CPU_MODE_VERBATIM,      PROC_p2
-pentium2,      CPU_MODE_VERBATIM,      PROC_p2
-pentium-2,     CPU_MODE_VERBATIM,      PROC_p2
-pentiumii,     CPU_MODE_VERBATIM,      PROC_p2
-pentium-ii,    CPU_MODE_VERBATIM,      PROC_p2
-p3,            CPU_MODE_VERBATIM,      PROC_p3
-pentium3,      CPU_MODE_VERBATIM,      PROC_p3
-pentium-3,     CPU_MODE_VERBATIM,      PROC_p3
-pentiumiii,    CPU_MODE_VERBATIM,      PROC_p3
-pentium-iii,   CPU_MODE_VERBATIM,      PROC_p3
-katmai,                CPU_MODE_VERBATIM,      PROC_p3
-p4,            CPU_MODE_VERBATIM,      PROC_p4
-pentium4,      CPU_MODE_VERBATIM,      PROC_p4
-pentium-4,     CPU_MODE_VERBATIM,      PROC_p4
-pentiumiv,     CPU_MODE_VERBATIM,      PROC_p4
-pentium-iv,    CPU_MODE_VERBATIM,      PROC_p4
-williamette,   CPU_MODE_VERBATIM,      PROC_p4
-ia64,          CPU_MODE_VERBATIM,      PROC_ia64
-ia-64,         CPU_MODE_VERBATIM,      PROC_ia64
-itanium,       CPU_MODE_VERBATIM,      PROC_ia64
-k6,            CPU_MODE_VERBATIM,      PROC_k6
-k7,            CPU_MODE_VERBATIM,      PROC_k7
-athlon,                CPU_MODE_VERBATIM,      PROC_k7
-hammer,                CPU_MODE_VERBATIM,      PROC_hammer
-sledgehammer,  CPU_MODE_VERBATIM,      PROC_hammer
-opteron,       CPU_MODE_VERBATIM,      PROC_hammer
-athlon64,      CPU_MODE_VERBATIM,      PROC_hammer
-athlon-64,     CPU_MODE_VERBATIM,      PROC_hammer
-prescott,      CPU_MODE_VERBATIM,      PROC_prescott
-conroe,                CPU_MODE_VERBATIM,      PROC_conroe
-penryn,                CPU_MODE_VERBATIM,      PROC_penryn
-nehalem,       CPU_MODE_VERBATIM,      PROC_nehalem
+8086,          x86_cpu_intel,  PROC_8086
+186,           x86_cpu_intel,  PROC_186
+80186,         x86_cpu_intel,  PROC_186
+i186,          x86_cpu_intel,  PROC_186
+286,           x86_cpu_intel,  PROC_286
+80286,         x86_cpu_intel,  PROC_286
+i286,          x86_cpu_intel,  PROC_286
+386,           x86_cpu_intel,  PROC_386
+80386,         x86_cpu_intel,  PROC_386
+i386,          x86_cpu_intel,  PROC_386
+486,           x86_cpu_intel,  PROC_486
+80486,         x86_cpu_intel,  PROC_486
+i486,          x86_cpu_intel,  PROC_486
+586,           x86_cpu_intel,  PROC_586
+i586,          x86_cpu_intel,  PROC_586
+pentium,       x86_cpu_intel,  PROC_586
+p5,            x86_cpu_intel,  PROC_586
+686,           x86_cpu_intel,  PROC_686
+i686,          x86_cpu_intel,  PROC_686
+p6,            x86_cpu_intel,  PROC_686
+ppro,          x86_cpu_intel,  PROC_686
+pentiumpro,    x86_cpu_intel,  PROC_686
+p2,            x86_cpu_intel,  PROC_p2
+pentium2,      x86_cpu_intel,  PROC_p2
+pentium-2,     x86_cpu_intel,  PROC_p2
+pentiumii,     x86_cpu_intel,  PROC_p2
+pentium-ii,    x86_cpu_intel,  PROC_p2
+p3,            x86_cpu_intel,  PROC_p3
+pentium3,      x86_cpu_intel,  PROC_p3
+pentium-3,     x86_cpu_intel,  PROC_p3
+pentiumiii,    x86_cpu_intel,  PROC_p3
+pentium-iii,   x86_cpu_intel,  PROC_p3
+katmai,                x86_cpu_intel,  PROC_p3
+p4,            x86_cpu_intel,  PROC_p4
+pentium4,      x86_cpu_intel,  PROC_p4
+pentium-4,     x86_cpu_intel,  PROC_p4
+pentiumiv,     x86_cpu_intel,  PROC_p4
+pentium-iv,    x86_cpu_intel,  PROC_p4
+williamette,   x86_cpu_intel,  PROC_p4
+ia64,          x86_cpu_ia64,   0
+ia-64,         x86_cpu_ia64,   0
+itanium,       x86_cpu_ia64,   0
+k6,            x86_cpu_amd,    PROC_k6
+k7,            x86_cpu_amd,    PROC_k7
+athlon,                x86_cpu_amd,    PROC_k7
+hammer,                x86_cpu_amd,    PROC_hammer
+sledgehammer,  x86_cpu_amd,    PROC_hammer
+opteron,       x86_cpu_amd,    PROC_hammer
+athlon64,      x86_cpu_amd,    PROC_hammer
+athlon-64,     x86_cpu_amd,    PROC_hammer
+prescott,      x86_cpu_intel,  PROC_prescott
+conroe,                x86_cpu_intel,  PROC_conroe
+penryn,                x86_cpu_intel,  PROC_penryn
+nehalem,       x86_cpu_intel,  PROC_nehalem
 #
 # Features have "no" versions to disable them, and only set/reset the
 # specific feature being changed.  All other bits are left alone.
 #
-fpu,           CPU_MODE_SET,   CPU_FPU
-nofpu,         CPU_MODE_CLEAR, CPU_FPU
-mmx,           CPU_MODE_SET,   CPU_MMX
-nommx,         CPU_MODE_CLEAR, CPU_MMX
-sse,           CPU_MODE_SET,   CPU_SSE
-nosse,         CPU_MODE_CLEAR, CPU_SSE
-sse2,          CPU_MODE_SET,   CPU_SSE2
-nosse2,                CPU_MODE_CLEAR, CPU_SSE2
-sse3,          CPU_MODE_SET,   CPU_SSE3
-nosse3,                CPU_MODE_CLEAR, CPU_SSE3
-#pni,          CPU_MODE_SET,   CPU_PNI
-#nopni,                CPU_MODE_CLEAR, CPU_PNI
-3dnow,         CPU_MODE_SET,   CPU_3DNow
-no3dnow,       CPU_MODE_CLEAR, CPU_3DNow
-cyrix,         CPU_MODE_SET,   CPU_Cyrix
-nocyrix,       CPU_MODE_CLEAR, CPU_Cyrix
-amd,           CPU_MODE_SET,   CPU_AMD
-noamd,         CPU_MODE_CLEAR, CPU_AMD
-smm,           CPU_MODE_SET,   CPU_SMM
-nosmm,         CPU_MODE_CLEAR, CPU_SMM
-prot,          CPU_MODE_SET,   CPU_Prot
-noprot,                CPU_MODE_CLEAR, CPU_Prot
-protected,     CPU_MODE_SET,   CPU_Prot
-noprotected,   CPU_MODE_CLEAR, CPU_Prot
-undoc,         CPU_MODE_SET,   CPU_Undoc
-noundoc,       CPU_MODE_CLEAR, CPU_Undoc
-undocumented,  CPU_MODE_SET,   CPU_Undoc
-noundocumented,        CPU_MODE_CLEAR, CPU_Undoc
-obs,           CPU_MODE_SET,   CPU_Obs
-noobs,         CPU_MODE_CLEAR, CPU_Obs
-obsolete,      CPU_MODE_SET,   CPU_Obs
-noobsolete,    CPU_MODE_CLEAR, CPU_Obs
-priv,          CPU_MODE_SET,   CPU_Priv
-nopriv,                CPU_MODE_CLEAR, CPU_Priv
-privileged,    CPU_MODE_SET,   CPU_Priv
-noprivileged,  CPU_MODE_CLEAR, CPU_Priv
-svm,           CPU_MODE_SET,   CPU_SVM
-nosvm,         CPU_MODE_CLEAR, CPU_SVM
-padlock,       CPU_MODE_SET,   CPU_PadLock
-nopadlock,     CPU_MODE_CLEAR, CPU_PadLock
-em64t,         CPU_MODE_SET,   CPU_EM64T
-noem64t,       CPU_MODE_CLEAR, CPU_EM64T
-ssse3,         CPU_MODE_SET,   CPU_SSSE3
-nossse3,       CPU_MODE_CLEAR, CPU_SSSE3
-sse4.1,                CPU_MODE_SET,   CPU_SSE41
-nosse4.1,      CPU_MODE_CLEAR, CPU_SSE41
-sse4.2,                CPU_MODE_SET,   CPU_SSE42
-nosse4.2,      CPU_MODE_CLEAR, CPU_SSE42
-sse4,          CPU_MODE_SET,   CPU_SSE4
-nosse4,                CPU_MODE_CLEAR, CPU_SSE4
+fpu,           x86_cpu_set,    CPU_FPU
+nofpu,         x86_cpu_clear,  CPU_FPU
+mmx,           x86_cpu_set,    CPU_MMX
+nommx,         x86_cpu_clear,  CPU_MMX
+sse,           x86_cpu_set,    CPU_SSE
+nosse,         x86_cpu_clear,  CPU_SSE
+sse2,          x86_cpu_set,    CPU_SSE2
+nosse2,                x86_cpu_clear,  CPU_SSE2
+sse3,          x86_cpu_set,    CPU_SSE3
+nosse3,                x86_cpu_clear,  CPU_SSE3
+#pni,          x86_cpu_set,    CPU_PNI
+#nopni,                x86_cpu_clear,  CPU_PNI
+3dnow,         x86_cpu_set,    CPU_3DNow
+no3dnow,       x86_cpu_clear,  CPU_3DNow
+cyrix,         x86_cpu_set,    CPU_Cyrix
+nocyrix,       x86_cpu_clear,  CPU_Cyrix
+amd,           x86_cpu_set,    CPU_AMD
+noamd,         x86_cpu_clear,  CPU_AMD
+smm,           x86_cpu_set,    CPU_SMM
+nosmm,         x86_cpu_clear,  CPU_SMM
+prot,          x86_cpu_set,    CPU_Prot
+noprot,                x86_cpu_clear,  CPU_Prot
+protected,     x86_cpu_set,    CPU_Prot
+noprotected,   x86_cpu_clear,  CPU_Prot
+undoc,         x86_cpu_set,    CPU_Undoc
+noundoc,       x86_cpu_clear,  CPU_Undoc
+undocumented,  x86_cpu_set,    CPU_Undoc
+noundocumented,        x86_cpu_clear,  CPU_Undoc
+obs,           x86_cpu_set,    CPU_Obs
+noobs,         x86_cpu_clear,  CPU_Obs
+obsolete,      x86_cpu_set,    CPU_Obs
+noobsolete,    x86_cpu_clear,  CPU_Obs
+priv,          x86_cpu_set,    CPU_Priv
+nopriv,                x86_cpu_clear,  CPU_Priv
+privileged,    x86_cpu_set,    CPU_Priv
+noprivileged,  x86_cpu_clear,  CPU_Priv
+svm,           x86_cpu_set,    CPU_SVM
+nosvm,         x86_cpu_clear,  CPU_SVM
+padlock,       x86_cpu_set,    CPU_PadLock
+nopadlock,     x86_cpu_clear,  CPU_PadLock
+em64t,         x86_cpu_set,    CPU_EM64T
+noem64t,       x86_cpu_clear,  CPU_EM64T
+ssse3,         x86_cpu_set,    CPU_SSSE3
+nossse3,       x86_cpu_clear,  CPU_SSSE3
+sse4.1,                x86_cpu_set,    CPU_SSE41
+nosse4.1,      x86_cpu_clear,  CPU_SSE41
+sse4.2,                x86_cpu_set,    CPU_SSE42
+nosse4.2,      x86_cpu_clear,  CPU_SSE42
+sse4,          x86_cpu_set_sse4,       0
+nosse4,                x86_cpu_clear_sse4,     0
 %%
 
 void
@@ -215,6 +310,8 @@ yasm_x86__parse_cpu(yasm_arch_x86 *arch_x86, const char *cpuid,
                     size_t cpuid_len)
 {
     /*@null@*/ const struct cpu_parse_data *pdata;
+    wordptr new_cpu;
+    unsigned int i;
 
     if (cpuid_len > 15)
         return;
@@ -226,15 +323,22 @@ yasm_x86__parse_cpu(yasm_arch_x86 *arch_x86, const char *cpuid,
         return;
     }
 
-    switch (pdata->mode) {
-        case CPU_MODE_VERBATIM:
-            arch_x86->cpu_enabled = pdata->cpu;
-            break;
-        case CPU_MODE_SET:
-            arch_x86->cpu_enabled |= pdata->cpu;
-            break;
-        case CPU_MODE_CLEAR:
-            arch_x86->cpu_enabled &= ~pdata->cpu;
-            break;
+    new_cpu = BitVector_Clone(arch_x86->cpu_enables[arch_x86->active_cpu]);
+    pdata->handler(new_cpu, pdata->data);
+
+    /* try to find an existing match in the CPU table first */
+    for (i=0; i<arch_x86->cpu_enables_size; i++) {
+        if (BitVector_equal(arch_x86->cpu_enables[i], new_cpu)) {
+            arch_x86->active_cpu = i;
+            BitVector_Destroy(new_cpu);
+            return;
+        }
     }
+
+    /* not found, need to add a new entry */
+    arch_x86->active_cpu = arch_x86->cpu_enables_size++;
+    arch_x86->cpu_enables =
+        yasm_xrealloc(arch_x86->cpu_enables,
+                      arch_x86->cpu_enables_size*sizeof(wordptr));
+    arch_x86->cpu_enables[arch_x86->active_cpu] = new_cpu;
 }
index 67b80a61e1c0ebd98fdc355256a4b3fd2378181a..9af6d0d7e5176a35a666aed4694682126f7b8af0 100644 (file)
@@ -34,7 +34,8 @@ RCSID("$Id$");
 #include "modules/arch/x86/x86arch.h"
 
 
-static const char *cpu_find_reverse(unsigned long cpu);
+static const char *cpu_find_reverse(unsigned int cpu0, unsigned int cpu1,
+                                    unsigned int cpu2);
 
 /* Opcode modifiers.  The opcode bytes are in "reverse" order because the
  * parameters are read from the arch-specific data in LSB->MSB order.
@@ -234,7 +235,9 @@ typedef struct x86_insn_info {
      * cpu_enabled to see if all bits set here are set in cpu_enabled--if so,
      * the instruction is available on this CPU.
      */
-    unsigned long cpu;
+    unsigned int cpu0:8;
+    unsigned int cpu1:8;
+    unsigned int cpu2:8;
 
     /* Opcode modifiers for variations of instruction.  As each modifier reads
      * its parameter in LSB->MSB order from the arch-specific data[1] from the
@@ -285,7 +288,7 @@ typedef struct x86_id_insn {
     /*@null@*/ const x86_insn_info *group;
 
     /* CPU feature flags enabled at the time of parsing the instruction */
-    unsigned long cpu_enabled;
+    wordptr cpu_enabled;
 
     /* Modifier data */
     unsigned long mod_data;
@@ -320,16 +323,6 @@ static const yasm_bytecode_callback x86_id_insn_callback = {
     YASM_BC_SPECIAL_INSN
 };
 
-/* Empty instruction */
-static const x86_insn_info empty_insn[] = {
-    { CPU_Any, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0 }
-};
-
-/* Placeholder for instructions invalid in 64-bit mode */
-static const x86_insn_info not64_insn[] = {
-    { CPU_Not64, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0 }
-};
-
 #include "x86insns.c"
 
 static void
@@ -473,15 +466,27 @@ x86_finalize_jmp(yasm_bytecode *bc, yasm_bytecode *prev_bc,
     jmp->nearop.len = 0;
     for (; num_info>0 && (jmp->shortop.len == 0 || jmp->nearop.len == 0);
          num_info--, info++) {
-        unsigned long cpu = info->cpu;
+        unsigned int cpu0 = info->cpu0;
+        unsigned int cpu1 = info->cpu1;
+        unsigned int cpu2 = info->cpu2;
 
-        if ((cpu & CPU_64) && mode_bits != 64)
+        /* Match CPU */
+        if (mode_bits != 64 &&
+            (cpu0 == CPU_64 || cpu1 == CPU_64 || cpu2 == CPU_64))
             continue;
-        if ((cpu & CPU_Not64) && mode_bits == 64)
+        if (mode_bits == 64 &&
+            (cpu0 == CPU_Not64 || cpu1 == CPU_Not64 || cpu2 == CPU_Not64))
             continue;
-        cpu &= ~(CPU_64 | CPU_Not64);
 
-        if ((id_insn->cpu_enabled & cpu) != cpu)
+        if (cpu0 == CPU_64 || cpu0 == CPU_Not64)
+            cpu0 = CPU_Any;
+        if (cpu1 == CPU_64 || cpu1 == CPU_Not64)
+            cpu1 = CPU_Any;
+        if (cpu2 == CPU_64 || cpu2 == CPU_Not64)
+            cpu2 = CPU_Any;
+        if (!BitVector_bit_test(id_insn->cpu_enabled, cpu0) ||
+            !BitVector_bit_test(id_insn->cpu_enabled, cpu1) ||
+            !BitVector_bit_test(id_insn->cpu_enabled, cpu2))
             continue;
 
         if (info->num_operands == 0)
@@ -539,6 +544,7 @@ x86_find_match(x86_id_insn *id_insn, yasm_insn_operand **ops,
     const x86_insn_info *info = id_insn->group;
     unsigned int num_info = id_insn->num_info;
     unsigned int suffix = id_insn->suffix;
+    unsigned int mode_bits = id_insn->mode_bits;
     int found = 0;
 
     /* Just do a simple linear search through the info array for a match.
@@ -547,21 +553,30 @@ x86_find_match(x86_id_insn *id_insn, yasm_insn_operand **ops,
     for (; num_info>0 && !found; num_info--, info++) {
         yasm_insn_operand *op, **use_ops;
         const unsigned long *info_ops = &insn_operands[info->operands_index];
-        unsigned long icpu;
+        unsigned int cpu0 = info->cpu0;
+        unsigned int cpu1 = info->cpu1;
+        unsigned int cpu2 = info->cpu2;
         unsigned int size;
         int mismatch = 0;
         int i;
 
         /* Match CPU */
-        icpu = info->cpu;
-
-        if ((icpu & CPU_64) && id_insn->mode_bits != 64)
+        if (mode_bits != 64 &&
+            (cpu0 == CPU_64 || cpu1 == CPU_64 || cpu2 == CPU_64))
             continue;
-        if ((icpu & CPU_Not64) && id_insn->mode_bits == 64)
+        if (mode_bits == 64 &&
+            (cpu0 == CPU_Not64 || cpu1 == CPU_Not64 || cpu2 == CPU_Not64))
             continue;
-        icpu &= ~(CPU_64 | CPU_Not64);
 
-        if (bypass != 7 && (id_insn->cpu_enabled & icpu) != icpu)
+        if (cpu0 == CPU_64 || cpu0 == CPU_Not64)
+            cpu0 = CPU_Any;
+        if (cpu1 == CPU_64 || cpu1 == CPU_Not64)
+            cpu1 = CPU_Any;
+        if (cpu2 == CPU_64 || cpu2 == CPU_Not64)
+            cpu2 = CPU_Any;
+        if (bypass != 7 && (!BitVector_bit_test(id_insn->cpu_enabled, cpu0) ||
+                            !BitVector_bit_test(id_insn->cpu_enabled, cpu1) ||
+                            !BitVector_bit_test(id_insn->cpu_enabled, cpu2)))
             continue;
 
         /* Match # of operands */
@@ -932,10 +947,13 @@ x86_match_error(x86_id_insn *id_insn, yasm_insn_operand **ops,
                            N_("invalid size for operand %d"), 3);
             break;
         case 7:
+        {
+            unsigned int cpu0 = i->cpu0, cpu1 = i->cpu1, cpu2 = i->cpu2;
             yasm_error_set(YASM_ERROR_TYPE,
                           N_("requires CPU%s"),
-                          cpu_find_reverse(i->cpu & ~(CPU_64 | CPU_Not64)));
+                          cpu_find_reverse(cpu0, cpu1, cpu2));
             break;
+        }
         default:
             yasm_error_set(YASM_ERROR_TYPE,
                            N_("invalid combination of opcode and operands"));
@@ -1371,6 +1389,17 @@ x86_id_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
     yasm_x86__bc_transform_insn(bc, insn);
 }
 
+/* suffix flags for instructions */
+enum {
+    NONE = 0,
+    SUF_B = (MOD_GasSufB >> MOD_GasSuf_SHIFT),
+    SUF_W = (MOD_GasSufW >> MOD_GasSuf_SHIFT),
+    SUF_L = (MOD_GasSufL >> MOD_GasSuf_SHIFT),
+    SUF_Q = (MOD_GasSufQ >> MOD_GasSuf_SHIFT),
+    SUF_S = (MOD_GasSufS >> MOD_GasSuf_SHIFT),
+    WEAK = 0x80     /* Relaxed operand mode for GAS */
+} flags;
+
 /* Static parse data structure for instructions */
 typedef struct insnprefix_parse_data {
     const char *name;
@@ -1384,100 +1413,102 @@ typedef struct insnprefix_parse_data {
      */
     unsigned long data1;
 
-    /* For instruction, cpu flags.
+    /* For instruction, suffix flags.
      * For prefix, prefix value.
      */
-    unsigned long data2;
-
-    /* suffix flags for instructions */
-    enum {
-        NONE = 0,
-        SUF_B = (MOD_GasSufB >> MOD_GasSuf_SHIFT),
-        SUF_W = (MOD_GasSufW >> MOD_GasSuf_SHIFT),
-        SUF_L = (MOD_GasSufL >> MOD_GasSuf_SHIFT),
-        SUF_Q = (MOD_GasSufQ >> MOD_GasSuf_SHIFT),
-        SUF_S = (MOD_GasSufS >> MOD_GasSuf_SHIFT),
-        WEAK = 0x80     /* Relaxed operand mode for GAS */
-    } flags;
+    unsigned int flags:8;
+
+    /* CPU flags */
+    unsigned int cpu0:8;
+    unsigned int cpu1:8;
+    unsigned int cpu2:8;
 } insnprefix_parse_data;
-#define PREFIX(name, type, value) \
-    { name, NULL, type, value, NONE }
 
 /* Pull in all parse data */
 #include "x86insn_nasm.c"
 #include "x86insn_gas.c"
 
 static const char *
-cpu_find_reverse(unsigned long cpu)
+cpu_find_reverse(unsigned int cpu0, unsigned int cpu1, unsigned int cpu2)
 {
     static char cpuname[200];
+    wordptr cpu = BitVector_Create(128, TRUE);
+
+    if (cpu0 != CPU_Any)
+        BitVector_Bit_On(cpu, cpu0);
+    if (cpu1 != CPU_Any)
+        BitVector_Bit_On(cpu, cpu1);
+    if (cpu2 != CPU_Any)
+        BitVector_Bit_On(cpu, cpu2);
 
     cpuname[0] = '\0';
 
-    if (cpu & CPU_Prot)
+    if (BitVector_bit_test(cpu, CPU_Prot))
         strcat(cpuname, " Protected");
-    if (cpu & CPU_Undoc)
+    if (BitVector_bit_test(cpu, CPU_Undoc))
         strcat(cpuname, " Undocumented");
-    if (cpu & CPU_Obs)
+    if (BitVector_bit_test(cpu, CPU_Obs))
         strcat(cpuname, " Obsolete");
-    if (cpu & CPU_Priv)
+    if (BitVector_bit_test(cpu, CPU_Priv))
         strcat(cpuname, " Privileged");
 
-    if (cpu & CPU_FPU)
+    if (BitVector_bit_test(cpu, CPU_FPU))
         strcat(cpuname, " FPU");
-    if (cpu & CPU_MMX)
+    if (BitVector_bit_test(cpu, CPU_MMX))
         strcat(cpuname, " MMX");
-    if (cpu & CPU_SSE)
+    if (BitVector_bit_test(cpu, CPU_SSE))
         strcat(cpuname, " SSE");
-    if (cpu & CPU_SSE2)
+    if (BitVector_bit_test(cpu, CPU_SSE2))
         strcat(cpuname, " SSE2");
-    if (cpu & CPU_SSE3)
+    if (BitVector_bit_test(cpu, CPU_SSE3))
         strcat(cpuname, " SSE3");
-    if (cpu & CPU_3DNow)
+    if (BitVector_bit_test(cpu, CPU_3DNow))
         strcat(cpuname, " 3DNow");
-    if (cpu & CPU_Cyrix)
+    if (BitVector_bit_test(cpu, CPU_Cyrix))
         strcat(cpuname, " Cyrix");
-    if (cpu & CPU_AMD)
+    if (BitVector_bit_test(cpu, CPU_AMD))
         strcat(cpuname, " AMD");
-    if (cpu & CPU_SMM)
+    if (BitVector_bit_test(cpu, CPU_SMM))
         strcat(cpuname, " SMM");
-    if (cpu & CPU_SVM)
+    if (BitVector_bit_test(cpu, CPU_SVM))
         strcat(cpuname, " SVM");
-    if (cpu & CPU_PadLock)
+    if (BitVector_bit_test(cpu, CPU_PadLock))
         strcat(cpuname, " PadLock");
-    if (cpu & CPU_EM64T)
+    if (BitVector_bit_test(cpu, CPU_EM64T))
         strcat(cpuname, " EM64T");
-    if (cpu & CPU_SSSE3)
+    if (BitVector_bit_test(cpu, CPU_SSSE3))
         strcat(cpuname, " SSSE3");
-    if (cpu & CPU_SSE41)
+    if (BitVector_bit_test(cpu, CPU_SSE41))
         strcat(cpuname, " SSE4.1");
-    if (cpu & CPU_SSE42)
+    if (BitVector_bit_test(cpu, CPU_SSE42))
         strcat(cpuname, " SSE4.2");
 
-    if (cpu & CPU_186)
+    if (BitVector_bit_test(cpu, CPU_186))
         strcat(cpuname, " 186");
-    if (cpu & CPU_286)
+    if (BitVector_bit_test(cpu, CPU_286))
         strcat(cpuname, " 286");
-    if (cpu & CPU_386)
+    if (BitVector_bit_test(cpu, CPU_386))
         strcat(cpuname, " 386");
-    if (cpu & CPU_486)
+    if (BitVector_bit_test(cpu, CPU_486))
         strcat(cpuname, " 486");
-    if (cpu & CPU_586)
+    if (BitVector_bit_test(cpu, CPU_586))
         strcat(cpuname, " 586");
-    if (cpu & CPU_686)
+    if (BitVector_bit_test(cpu, CPU_686))
         strcat(cpuname, " 686");
-    if (cpu & CPU_P3)
+    if (BitVector_bit_test(cpu, CPU_P3))
         strcat(cpuname, " P3");
-    if (cpu & CPU_P4)
+    if (BitVector_bit_test(cpu, CPU_P4))
         strcat(cpuname, " P4");
-    if (cpu & CPU_IA64)
+    if (BitVector_bit_test(cpu, CPU_IA64))
         strcat(cpuname, " IA64");
-    if (cpu & CPU_K6)
+    if (BitVector_bit_test(cpu, CPU_K6))
         strcat(cpuname, " K6");
-    if (cpu & CPU_Athlon)
+    if (BitVector_bit_test(cpu, CPU_Athlon))
         strcat(cpuname, " Athlon");
-    if (cpu & CPU_Hammer)
+    if (BitVector_bit_test(cpu, CPU_Hammer))
         strcat(cpuname, " Hammer");
+
+    BitVector_Destroy(cpu);
     return cpuname;
 }
 
@@ -1488,6 +1519,7 @@ yasm_x86__parse_check_insnprefix(yasm_arch *arch, const char *id,
 {
     yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
     /*@null@*/ const insnprefix_parse_data *pdata;
+    unsigned int cpu0, cpu1, cpu2;
     size_t i;
     static char lcaseid[16];
 
@@ -1513,22 +1545,28 @@ yasm_x86__parse_check_insnprefix(yasm_arch *arch, const char *id,
     if (!pdata)
         return YASM_ARCH_NOTINSNPREFIX;
 
+    cpu0 = pdata->cpu0;
+    cpu1 = pdata->cpu1;
+    cpu2 = pdata->cpu2;
+
     if (pdata->group) {
-        unsigned long cpu = pdata->data2;
         x86_id_insn *id_insn;
+        wordptr cpu_enabled = arch_x86->cpu_enables[arch_x86->active_cpu];
 
-        if ((cpu & CPU_64) && arch_x86->mode_bits != 64) {
+        if (arch_x86->mode_bits != 64 &&
+            (cpu0 == CPU_64 || cpu1 == CPU_64 || cpu2 == CPU_64)) {
             yasm_warn_set(YASM_WARN_GENERAL,
                           N_("`%s' is an instruction in 64-bit mode"), id);
             return YASM_ARCH_NOTINSNPREFIX;
         }
-        if ((cpu & CPU_Not64) && arch_x86->mode_bits == 64) {
+        if (arch_x86->mode_bits == 64 &&
+            (cpu0 == CPU_Not64 || cpu1 == CPU_Not64 || cpu2 == CPU_Not64)) {
             yasm_error_set(YASM_ERROR_GENERAL,
                            N_("`%s' invalid in 64-bit mode"), id);
             id_insn = yasm_xmalloc(sizeof(x86_id_insn));
             yasm_insn_initialize(&id_insn->insn);
             id_insn->group = not64_insn;
-            id_insn->cpu_enabled = CPU_Not64;
+            id_insn->cpu_enabled = cpu_enabled;
             id_insn->mod_data = 0;
             id_insn->num_info = NELEMS(not64_insn);
             id_insn->mode_bits = arch_x86->mode_bits;
@@ -1539,18 +1577,25 @@ yasm_x86__parse_check_insnprefix(yasm_arch *arch, const char *id,
             return YASM_ARCH_INSN;
         }
 
-        cpu &= ~(CPU_64 | CPU_Not64);
-        if ((arch_x86->cpu_enabled & cpu) != cpu) {
+        if (cpu0 == CPU_64 || cpu0 == CPU_Not64)
+            cpu0 = CPU_Any;
+        if (cpu1 == CPU_64 || cpu1 == CPU_Not64)
+            cpu1 = CPU_Any;
+        if (cpu2 == CPU_64 || cpu2 == CPU_Not64)
+            cpu2 = CPU_Any;
+        if (!BitVector_bit_test(cpu_enabled, cpu0) ||
+            !BitVector_bit_test(cpu_enabled, cpu1) ||
+            !BitVector_bit_test(cpu_enabled, cpu2)) {
             yasm_warn_set(YASM_WARN_GENERAL,
                           N_("`%s' is an instruction in CPU%s"), id,
-                          cpu_find_reverse(cpu));
+                          cpu_find_reverse(cpu0, cpu1, cpu2));
             return YASM_ARCH_NOTINSNPREFIX;
         }
 
         id_insn = yasm_xmalloc(sizeof(x86_id_insn));
         yasm_insn_initialize(&id_insn->insn);
         id_insn->group = pdata->group;
-        id_insn->cpu_enabled = arch_x86->cpu_enabled;
+        id_insn->cpu_enabled = cpu_enabled;
         id_insn->mod_data = pdata->data1 >> 8;
         id_insn->num_info = pdata->data1 & 0xff;
         id_insn->mode_bits = arch_x86->mode_bits;
@@ -1561,7 +1606,7 @@ yasm_x86__parse_check_insnprefix(yasm_arch *arch, const char *id,
         return YASM_ARCH_INSN;
     } else {
         unsigned long type = pdata->data1;
-        unsigned long value = pdata->data2;
+        unsigned long value = pdata->flags;
 
         if (arch_x86->mode_bits == 64 && type == X86_OPERSIZE && value == 32) {
             yasm_error_set(YASM_ERROR_GENERAL,
@@ -1575,9 +1620,8 @@ yasm_x86__parse_check_insnprefix(yasm_arch *arch, const char *id,
             return YASM_ARCH_NOTINSNPREFIX;
         }
 
-        if ((type == X86_REX ||
-             (value == 64 && (type == X86_OPERSIZE || type == X86_ADDRSIZE)))
-            && arch_x86->mode_bits != 64) {
+        if (arch_x86->mode_bits != 64 &&
+            (cpu0 == CPU_64 || cpu1 == CPU_64 || cpu2 == CPU_64)) {
             yasm_warn_set(YASM_WARN_GENERAL,
                           N_("`%s' is a prefix in 64-bit mode"), id);
             return YASM_ARCH_NOTINSNPREFIX;
@@ -1611,7 +1655,7 @@ yasm_x86__create_empty_insn(yasm_arch *arch, unsigned long line)
 
     yasm_insn_initialize(&id_insn->insn);
     id_insn->group = empty_insn;
-    id_insn->cpu_enabled = arch_x86->cpu_enabled;
+    id_insn->cpu_enabled = arch_x86->cpu_enables[arch_x86->active_cpu];
     id_insn->mod_data = 0;
     id_insn->num_info = NELEMS(empty_insn);
     id_insn->mode_bits = arch_x86->mode_bits;