1# 2# x86 CPU recognition 3# 4# Copyright (C) 2002-2007 Peter Johnson 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' 16# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE 19# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25# POSSIBILITY OF SUCH DAMAGE. 26%{ 27#include <util.h> 28 29#include <ctype.h> 30#include <libyasm.h> 31#include <libyasm/phash.h> 32 33#include "modules/arch/x86/x86arch.h" 34 35#define PROC_8086 0 36#define PROC_186 1 37#define PROC_286 2 38#define PROC_386 3 39#define PROC_486 4 40#define PROC_586 5 41#define PROC_686 6 42#define PROC_p2 7 43#define PROC_p3 8 44#define PROC_p4 9 45#define PROC_prescott 10 46#define PROC_conroe 11 47#define PROC_penryn 12 48#define PROC_nehalem 13 49#define PROC_westmere 14 50#define PROC_sandybridge 15 51 52static void 53x86_cpu_intel(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data) 54{ 55 BitVector_Empty(cpu); 56 57 BitVector_Bit_On(cpu, CPU_Priv); 58 if (data >= PROC_286) 59 BitVector_Bit_On(cpu, CPU_Prot); 60 if (data >= PROC_386) 61 BitVector_Bit_On(cpu, CPU_SMM); 62 if (data >= PROC_sandybridge) 63 BitVector_Bit_On(cpu, CPU_AVX); 64 if (data >= PROC_westmere) { 65 BitVector_Bit_On(cpu, CPU_AES); 66 BitVector_Bit_On(cpu, CPU_CLMUL); 67 } 68 if (data >= PROC_nehalem) { 69 BitVector_Bit_On(cpu, CPU_SSE42); 70 BitVector_Bit_On(cpu, CPU_XSAVE); 71 } 72 if (data >= PROC_penryn) 73 BitVector_Bit_On(cpu, CPU_SSE41); 74 if (data >= PROC_conroe) 75 BitVector_Bit_On(cpu, CPU_SSSE3); 76 if (data >= PROC_prescott) 77 BitVector_Bit_On(cpu, CPU_SSE3); 78 if (data >= PROC_p4) 79 BitVector_Bit_On(cpu, CPU_SSE2); 80 if (data >= PROC_p3) 81 BitVector_Bit_On(cpu, CPU_SSE); 82 if (data >= PROC_p2) 83 BitVector_Bit_On(cpu, CPU_MMX); 84 if (data >= PROC_486) 85 BitVector_Bit_On(cpu, CPU_FPU); 86 if (data >= PROC_prescott) 87 BitVector_Bit_On(cpu, CPU_EM64T); 88 89 if (data >= PROC_p4) 90 BitVector_Bit_On(cpu, CPU_P4); 91 if (data >= PROC_p3) 92 BitVector_Bit_On(cpu, CPU_P3); 93 if (data >= PROC_686) 94 BitVector_Bit_On(cpu, CPU_686); 95 if (data >= PROC_586) 96 BitVector_Bit_On(cpu, CPU_586); 97 if (data >= PROC_486) 98 BitVector_Bit_On(cpu, CPU_486); 99 if (data >= PROC_386) 100 BitVector_Bit_On(cpu, CPU_386); 101 if (data >= PROC_286) 102 BitVector_Bit_On(cpu, CPU_286); 103 if (data >= PROC_186) 104 BitVector_Bit_On(cpu, CPU_186); 105 BitVector_Bit_On(cpu, CPU_086); 106 107 /* Use Intel long NOPs if 686 or better */ 108 if (data >= PROC_686) 109 arch_x86->nop = X86_NOP_INTEL; 110 else 111 arch_x86->nop = X86_NOP_BASIC; 112} 113 114static void 115x86_cpu_ia64(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data) 116{ 117 BitVector_Empty(cpu); 118 BitVector_Bit_On(cpu, CPU_Priv); 119 BitVector_Bit_On(cpu, CPU_Prot); 120 BitVector_Bit_On(cpu, CPU_SMM); 121 BitVector_Bit_On(cpu, CPU_SSE2); 122 BitVector_Bit_On(cpu, CPU_SSE); 123 BitVector_Bit_On(cpu, CPU_MMX); 124 BitVector_Bit_On(cpu, CPU_FPU); 125 BitVector_Bit_On(cpu, CPU_IA64); 126 BitVector_Bit_On(cpu, CPU_P4); 127 BitVector_Bit_On(cpu, CPU_P3); 128 BitVector_Bit_On(cpu, CPU_686); 129 BitVector_Bit_On(cpu, CPU_586); 130 BitVector_Bit_On(cpu, CPU_486); 131 BitVector_Bit_On(cpu, CPU_386); 132 BitVector_Bit_On(cpu, CPU_286); 133 BitVector_Bit_On(cpu, CPU_186); 134 BitVector_Bit_On(cpu, CPU_086); 135} 136 137#define PROC_bulldozer 11 138#define PROC_k10 10 139#define PROC_venice 9 140#define PROC_hammer 8 141#define PROC_k7 7 142#define PROC_k6 6 143 144static void 145x86_cpu_amd(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data) 146{ 147 BitVector_Empty(cpu); 148 149 BitVector_Bit_On(cpu, CPU_Priv); 150 BitVector_Bit_On(cpu, CPU_Prot); 151 BitVector_Bit_On(cpu, CPU_SMM); 152 BitVector_Bit_On(cpu, CPU_3DNow); 153 if (data >= PROC_bulldozer) { 154 BitVector_Bit_On(cpu, CPU_XOP); 155 BitVector_Bit_On(cpu, CPU_FMA4); 156 } 157 if (data >= PROC_k10) 158 BitVector_Bit_On(cpu, CPU_SSE4a); 159 if (data >= PROC_venice) 160 BitVector_Bit_On(cpu, CPU_SSE3); 161 if (data >= PROC_hammer) 162 BitVector_Bit_On(cpu, CPU_SSE2); 163 if (data >= PROC_k7) 164 BitVector_Bit_On(cpu, CPU_SSE); 165 if (data >= PROC_k6) 166 BitVector_Bit_On(cpu, CPU_MMX); 167 BitVector_Bit_On(cpu, CPU_FPU); 168 169 if (data >= PROC_hammer) 170 BitVector_Bit_On(cpu, CPU_Hammer); 171 if (data >= PROC_k7) 172 BitVector_Bit_On(cpu, CPU_Athlon); 173 if (data >= PROC_k6) 174 BitVector_Bit_On(cpu, CPU_K6); 175 BitVector_Bit_On(cpu, CPU_686); 176 BitVector_Bit_On(cpu, CPU_586); 177 BitVector_Bit_On(cpu, CPU_486); 178 BitVector_Bit_On(cpu, CPU_386); 179 BitVector_Bit_On(cpu, CPU_286); 180 BitVector_Bit_On(cpu, CPU_186); 181 BitVector_Bit_On(cpu, CPU_086); 182 183 /* Use AMD long NOPs if k6 or better */ 184 if (data >= PROC_k6) 185 arch_x86->nop = X86_NOP_AMD; 186 else 187 arch_x86->nop = X86_NOP_BASIC; 188} 189 190static void 191x86_cpu_set(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data) 192{ 193 BitVector_Bit_On(cpu, data); 194} 195 196static void 197x86_cpu_clear(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data) 198{ 199 BitVector_Bit_Off(cpu, data); 200} 201 202static void 203x86_cpu_set_sse4(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data) 204{ 205 BitVector_Bit_On(cpu, CPU_SSE41); 206 BitVector_Bit_On(cpu, CPU_SSE42); 207} 208 209static void 210x86_cpu_clear_sse4(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data) 211{ 212 BitVector_Bit_Off(cpu, CPU_SSE41); 213 BitVector_Bit_Off(cpu, CPU_SSE42); 214} 215 216static void 217x86_nop(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data) 218{ 219 arch_x86->nop = data; 220} 221 222%} 223%ignore-case 224%language=ANSI-C 225%compare-strncmp 226%readonly-tables 227%enum 228%struct-type 229%define hash-function-name cpu_hash 230%define lookup-function-name cpu_find 231struct cpu_parse_data { 232 const char *name; 233 void (*handler) (wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data); 234 unsigned int data; 235}; 236%% 2378086, x86_cpu_intel, PROC_8086 238186, x86_cpu_intel, PROC_186 23980186, x86_cpu_intel, PROC_186 240i186, x86_cpu_intel, PROC_186 241286, x86_cpu_intel, PROC_286 24280286, x86_cpu_intel, PROC_286 243i286, x86_cpu_intel, PROC_286 244386, x86_cpu_intel, PROC_386 24580386, x86_cpu_intel, PROC_386 246i386, x86_cpu_intel, PROC_386 247486, x86_cpu_intel, PROC_486 24880486, x86_cpu_intel, PROC_486 249i486, x86_cpu_intel, PROC_486 250586, x86_cpu_intel, PROC_586 251i586, x86_cpu_intel, PROC_586 252pentium, x86_cpu_intel, PROC_586 253p5, x86_cpu_intel, PROC_586 254686, x86_cpu_intel, PROC_686 255i686, x86_cpu_intel, PROC_686 256p6, x86_cpu_intel, PROC_686 257ppro, x86_cpu_intel, PROC_686 258pentiumpro, x86_cpu_intel, PROC_686 259p2, x86_cpu_intel, PROC_p2 260pentium2, x86_cpu_intel, PROC_p2 261pentium-2, x86_cpu_intel, PROC_p2 262pentiumii, x86_cpu_intel, PROC_p2 263pentium-ii, x86_cpu_intel, PROC_p2 264p3, x86_cpu_intel, PROC_p3 265pentium3, x86_cpu_intel, PROC_p3 266pentium-3, x86_cpu_intel, PROC_p3 267pentiumiii, x86_cpu_intel, PROC_p3 268pentium-iii, x86_cpu_intel, PROC_p3 269katmai, x86_cpu_intel, PROC_p3 270p4, x86_cpu_intel, PROC_p4 271pentium4, x86_cpu_intel, PROC_p4 272pentium-4, x86_cpu_intel, PROC_p4 273pentiumiv, x86_cpu_intel, PROC_p4 274pentium-iv, x86_cpu_intel, PROC_p4 275williamette, x86_cpu_intel, PROC_p4 276ia64, x86_cpu_ia64, 0 277ia-64, x86_cpu_ia64, 0 278itanium, x86_cpu_ia64, 0 279k6, x86_cpu_amd, PROC_k6 280k7, x86_cpu_amd, PROC_k7 281athlon, x86_cpu_amd, PROC_k7 282k8, x86_cpu_amd, PROC_hammer 283hammer, x86_cpu_amd, PROC_hammer 284clawhammer, x86_cpu_amd, PROC_hammer 285opteron, x86_cpu_amd, PROC_hammer 286athlon64, x86_cpu_amd, PROC_hammer 287athlon-64, x86_cpu_amd, PROC_hammer 288venice, x86_cpu_amd, PROC_venice 289k10, x86_cpu_amd, PROC_k10 290phenom, x86_cpu_amd, PROC_k10 291family10h, x86_cpu_amd, PROC_k10 292bulldozer, x86_cpu_amd, PROC_bulldozer 293prescott, x86_cpu_intel, PROC_prescott 294conroe, x86_cpu_intel, PROC_conroe 295core2, x86_cpu_intel, PROC_conroe 296penryn, x86_cpu_intel, PROC_penryn 297nehalem, x86_cpu_intel, PROC_nehalem 298corei7, x86_cpu_intel, PROC_nehalem 299westmere, x86_cpu_intel, PROC_westmere 300sandybridge, x86_cpu_intel, PROC_sandybridge 301# 302# Features have "no" versions to disable them, and only set/reset the 303# specific feature being changed. All other bits are left alone. 304# 305fpu, x86_cpu_set, CPU_FPU 306nofpu, x86_cpu_clear, CPU_FPU 307mmx, x86_cpu_set, CPU_MMX 308nommx, x86_cpu_clear, CPU_MMX 309sse, x86_cpu_set, CPU_SSE 310nosse, x86_cpu_clear, CPU_SSE 311sse2, x86_cpu_set, CPU_SSE2 312nosse2, x86_cpu_clear, CPU_SSE2 313sse3, x86_cpu_set, CPU_SSE3 314nosse3, x86_cpu_clear, CPU_SSE3 315#pni, x86_cpu_set, CPU_PNI 316#nopni, x86_cpu_clear, CPU_PNI 3173dnow, x86_cpu_set, CPU_3DNow 318no3dnow, x86_cpu_clear, CPU_3DNow 319cyrix, x86_cpu_set, CPU_Cyrix 320nocyrix, x86_cpu_clear, CPU_Cyrix 321amd, x86_cpu_set, CPU_AMD 322noamd, x86_cpu_clear, CPU_AMD 323smm, x86_cpu_set, CPU_SMM 324nosmm, x86_cpu_clear, CPU_SMM 325prot, x86_cpu_set, CPU_Prot 326noprot, x86_cpu_clear, CPU_Prot 327protected, x86_cpu_set, CPU_Prot 328noprotected, x86_cpu_clear, CPU_Prot 329undoc, x86_cpu_set, CPU_Undoc 330noundoc, x86_cpu_clear, CPU_Undoc 331undocumented, x86_cpu_set, CPU_Undoc 332noundocumented, x86_cpu_clear, CPU_Undoc 333obs, x86_cpu_set, CPU_Obs 334noobs, x86_cpu_clear, CPU_Obs 335obsolete, x86_cpu_set, CPU_Obs 336noobsolete, x86_cpu_clear, CPU_Obs 337priv, x86_cpu_set, CPU_Priv 338nopriv, x86_cpu_clear, CPU_Priv 339privileged, x86_cpu_set, CPU_Priv 340noprivileged, x86_cpu_clear, CPU_Priv 341svm, x86_cpu_set, CPU_SVM 342nosvm, x86_cpu_clear, CPU_SVM 343padlock, x86_cpu_set, CPU_PadLock 344nopadlock, x86_cpu_clear, CPU_PadLock 345em64t, x86_cpu_set, CPU_EM64T 346noem64t, x86_cpu_clear, CPU_EM64T 347ssse3, x86_cpu_set, CPU_SSSE3 348nossse3, x86_cpu_clear, CPU_SSSE3 349sse4.1, x86_cpu_set, CPU_SSE41 350nosse4.1, x86_cpu_clear, CPU_SSE41 351sse41, x86_cpu_set, CPU_SSE41 352nosse41, x86_cpu_clear, CPU_SSE41 353sse4.2, x86_cpu_set, CPU_SSE42 354nosse4.2, x86_cpu_clear, CPU_SSE42 355sse42, x86_cpu_set, CPU_SSE42 356nosse42, x86_cpu_clear, CPU_SSE42 357sse4a, x86_cpu_set, CPU_SSE4a 358nosse4a, x86_cpu_clear, CPU_SSE4a 359sse4, x86_cpu_set_sse4, 0 360nosse4, x86_cpu_clear_sse4, 0 361xsave, x86_cpu_set, CPU_XSAVE 362noxsave, x86_cpu_clear, CPU_XSAVE 363avx, x86_cpu_set, CPU_AVX 364noavx, x86_cpu_clear, CPU_AVX 365fma, x86_cpu_set, CPU_FMA 366nofma, x86_cpu_clear, CPU_FMA 367aes, x86_cpu_set, CPU_AES 368noaes, x86_cpu_clear, CPU_AES 369clmul, x86_cpu_set, CPU_CLMUL 370noclmul, x86_cpu_clear, CPU_CLMUL 371pclmulqdq, x86_cpu_set, CPU_CLMUL 372nopclmulqdq, x86_cpu_clear, CPU_CLMUL 373movbe, x86_cpu_set, CPU_MOVBE 374nomovbe, x86_cpu_clear, CPU_MOVBE 375xop, x86_cpu_set, CPU_XOP 376noxop, x86_cpu_clear, CPU_XOP 377fma4, x86_cpu_set, CPU_FMA4 378nofma4, x86_cpu_clear, CPU_FMA4 379f16c, x86_cpu_set, CPU_F16C 380nof16c, x86_cpu_clear, CPU_F16C 381fsgsbase, x86_cpu_set, CPU_FSGSBASE 382nofsgsbase, x86_cpu_clear, CPU_FSGSBASE 383rdrand, x86_cpu_set, CPU_RDRAND 384nordrand, x86_cpu_clear, CPU_RDRAND 385xsaveopt, x86_cpu_set, CPU_XSAVEOPT 386noxsaveopt, x86_cpu_clear, CPU_XSAVEOPT 387eptvpid, x86_cpu_set, CPU_EPTVPID 388noeptvpid, x86_cpu_clear, CPU_EPTVPID 389smx, x86_cpu_set, CPU_SMX 390nosmx, x86_cpu_clear, CPU_SMX 391avx2, x86_cpu_set, CPU_AVX2 392noavx2, x86_cpu_clear, CPU_AVX2 393bmi1, x86_cpu_set, CPU_BMI1 394nobmi1, x86_cpu_clear, CPU_BMI1 395bmi2, x86_cpu_set, CPU_BMI2 396nobmi2, x86_cpu_clear, CPU_BMI2 397invpcid, x86_cpu_set, CPU_INVPCID 398noinvpcid, x86_cpu_clear, CPU_INVPCID 399lzcnt, x86_cpu_set, CPU_LZCNT 400nolzcnt, x86_cpu_clear, CPU_LZCNT 401# Change NOP patterns 402basicnop, x86_nop, X86_NOP_BASIC 403intelnop, x86_nop, X86_NOP_INTEL 404amdnop, x86_nop, X86_NOP_AMD 405%% 406 407void 408yasm_x86__parse_cpu(yasm_arch_x86 *arch_x86, const char *cpuid, 409 size_t cpuid_len) 410{ 411 /*@null@*/ const struct cpu_parse_data *pdata; 412 wordptr new_cpu; 413 size_t i; 414 static char lcaseid[16]; 415 416 if (cpuid_len > 15) 417 return; 418 for (i=0; i<cpuid_len; i++) 419 lcaseid[i] = tolower(cpuid[i]); 420 lcaseid[cpuid_len] = '\0'; 421 422 pdata = cpu_find(lcaseid, cpuid_len); 423 if (!pdata) { 424 yasm_warn_set(YASM_WARN_GENERAL, 425 N_("unrecognized CPU identifier `%s'"), cpuid); 426 return; 427 } 428 429 new_cpu = BitVector_Clone(arch_x86->cpu_enables[arch_x86->active_cpu]); 430 pdata->handler(new_cpu, arch_x86, pdata->data); 431 432 /* try to find an existing match in the CPU table first */ 433 for (i=0; i<arch_x86->cpu_enables_size; i++) { 434 if (BitVector_equal(arch_x86->cpu_enables[i], new_cpu)) { 435 arch_x86->active_cpu = i; 436 BitVector_Destroy(new_cpu); 437 return; 438 } 439 } 440 441 /* not found, need to add a new entry */ 442 arch_x86->active_cpu = arch_x86->cpu_enables_size++; 443 arch_x86->cpu_enables = 444 yasm_xrealloc(arch_x86->cpu_enables, 445 arch_x86->cpu_enables_size*sizeof(wordptr)); 446 arch_x86->cpu_enables[arch_x86->active_cpu] = new_cpu; 447} 448