From: Peter Johnson Date: Wed, 12 Sep 2007 06:55:51 +0000 (-0000) Subject: Restructure x86 CPU handling to allow for more than 30 CPU feature flags. X-Git-Tag: v0.6.2~6^2~15 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f61ca1e37934ec87478520fb3c586028408e670a;p=yasm Restructure x86 CPU handling to allow for more than 30 CPU feature flags. svn path=/trunk/yasm/; revision=1945 --- diff --git a/modules/arch/x86/gen_x86_insn.py b/modules/arch/x86/gen_x86_insn.py index f862f8ed..41265967 100755 --- a/modules/arch/x86/gen_x86_insn.py +++ b/modules/arch/x86/gen_x86_insn.py @@ -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 # diff --git a/modules/arch/x86/x86arch.c b/modules/arch/x86/x86arch.c index 0f8c9527..d410ac0e 100644 --- a/modules/arch/x86/x86arch.c +++ b/modules/arch/x86/x86arch.c @@ -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; icpu_enables_size; i++) + BitVector_Destroy(arch_x86->cpu_enables[i]); + yasm_xfree(arch_x86->cpu_enables); yasm_xfree(arch); } diff --git a/modules/arch/x86/x86arch.h b/modules/arch/x86/x86arch.h index cbe26f48..efd8e74f 100644 --- a/modules/arch/x86/x86arch.h +++ b/modules/arch/x86/x86arch.h @@ -27,53 +27,57 @@ #ifndef YASM_X86ARCH_H #define YASM_X86ARCH_H +#include + /* 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, diff --git a/modules/arch/x86/x86cpu.gperf b/modules/arch/x86/x86cpu.gperf index 84f4d9fb..1feae1db 100644 --- a/modules/arch/x86/x86cpu.gperf +++ b/modules/arch/x86/x86cpu.gperf @@ -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; icpu_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; } diff --git a/modules/arch/x86/x86id.c b/modules/arch/x86/x86id.c index 67b80a61..9af6d0d7 100644 --- a/modules/arch/x86/x86id.c +++ b/modules/arch/x86/x86id.c @@ -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;