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 52 static void 53 x86_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 114 static void 115 x86_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 144 static void 145 x86_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 190 static void 191 x86_cpu_set(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data) 192 { 193 BitVector_Bit_On(cpu, data); 194 } 195 196 static void 197 x86_cpu_clear(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data) 198 { 199 BitVector_Bit_Off(cpu, data); 200 } 201 202 static void 203 x86_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 209 static void 210 x86_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 216 static void 217 x86_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 231 struct 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 %% 237 8086, x86_cpu_intel, PROC_8086 238 186, x86_cpu_intel, PROC_186 239 80186, x86_cpu_intel, PROC_186 240 i186, x86_cpu_intel, PROC_186 241 286, x86_cpu_intel, PROC_286 242 80286, x86_cpu_intel, PROC_286 243 i286, x86_cpu_intel, PROC_286 244 386, x86_cpu_intel, PROC_386 245 80386, x86_cpu_intel, PROC_386 246 i386, x86_cpu_intel, PROC_386 247 486, x86_cpu_intel, PROC_486 248 80486, x86_cpu_intel, PROC_486 249 i486, x86_cpu_intel, PROC_486 250 586, x86_cpu_intel, PROC_586 251 i586, x86_cpu_intel, PROC_586 252 pentium, x86_cpu_intel, PROC_586 253 p5, x86_cpu_intel, PROC_586 254 686, x86_cpu_intel, PROC_686 255 i686, x86_cpu_intel, PROC_686 256 p6, x86_cpu_intel, PROC_686 257 ppro, x86_cpu_intel, PROC_686 258 pentiumpro, x86_cpu_intel, PROC_686 259 p2, x86_cpu_intel, PROC_p2 260 pentium2, x86_cpu_intel, PROC_p2 261 pentium-2, x86_cpu_intel, PROC_p2 262 pentiumii, x86_cpu_intel, PROC_p2 263 pentium-ii, x86_cpu_intel, PROC_p2 264 p3, x86_cpu_intel, PROC_p3 265 pentium3, x86_cpu_intel, PROC_p3 266 pentium-3, x86_cpu_intel, PROC_p3 267 pentiumiii, x86_cpu_intel, PROC_p3 268 pentium-iii, x86_cpu_intel, PROC_p3 269 katmai, x86_cpu_intel, PROC_p3 270 p4, x86_cpu_intel, PROC_p4 271 pentium4, x86_cpu_intel, PROC_p4 272 pentium-4, x86_cpu_intel, PROC_p4 273 pentiumiv, x86_cpu_intel, PROC_p4 274 pentium-iv, x86_cpu_intel, PROC_p4 275 williamette, x86_cpu_intel, PROC_p4 276 ia64, x86_cpu_ia64, 0 277 ia-64, x86_cpu_ia64, 0 278 itanium, x86_cpu_ia64, 0 279 k6, x86_cpu_amd, PROC_k6 280 k7, x86_cpu_amd, PROC_k7 281 athlon, x86_cpu_amd, PROC_k7 282 k8, x86_cpu_amd, PROC_hammer 283 hammer, x86_cpu_amd, PROC_hammer 284 clawhammer, x86_cpu_amd, PROC_hammer 285 opteron, x86_cpu_amd, PROC_hammer 286 athlon64, x86_cpu_amd, PROC_hammer 287 athlon-64, x86_cpu_amd, PROC_hammer 288 venice, x86_cpu_amd, PROC_venice 289 k10, x86_cpu_amd, PROC_k10 290 phenom, x86_cpu_amd, PROC_k10 291 family10h, x86_cpu_amd, PROC_k10 292 bulldozer, x86_cpu_amd, PROC_bulldozer 293 prescott, x86_cpu_intel, PROC_prescott 294 conroe, x86_cpu_intel, PROC_conroe 295 core2, x86_cpu_intel, PROC_conroe 296 penryn, x86_cpu_intel, PROC_penryn 297 nehalem, x86_cpu_intel, PROC_nehalem 298 corei7, x86_cpu_intel, PROC_nehalem 299 westmere, x86_cpu_intel, PROC_westmere 300 sandybridge, 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 # 305 fpu, x86_cpu_set, CPU_FPU 306 nofpu, x86_cpu_clear, CPU_FPU 307 mmx, x86_cpu_set, CPU_MMX 308 nommx, x86_cpu_clear, CPU_MMX 309 sse, x86_cpu_set, CPU_SSE 310 nosse, x86_cpu_clear, CPU_SSE 311 sse2, x86_cpu_set, CPU_SSE2 312 nosse2, x86_cpu_clear, CPU_SSE2 313 sse3, x86_cpu_set, CPU_SSE3 314 nosse3, x86_cpu_clear, CPU_SSE3 315 #pni, x86_cpu_set, CPU_PNI 316 #nopni, x86_cpu_clear, CPU_PNI 317 3dnow, x86_cpu_set, CPU_3DNow 318 no3dnow, x86_cpu_clear, CPU_3DNow 319 cyrix, x86_cpu_set, CPU_Cyrix 320 nocyrix, x86_cpu_clear, CPU_Cyrix 321 amd, x86_cpu_set, CPU_AMD 322 noamd, x86_cpu_clear, CPU_AMD 323 smm, x86_cpu_set, CPU_SMM 324 nosmm, x86_cpu_clear, CPU_SMM 325 prot, x86_cpu_set, CPU_Prot 326 noprot, x86_cpu_clear, CPU_Prot 327 protected, x86_cpu_set, CPU_Prot 328 noprotected, x86_cpu_clear, CPU_Prot 329 undoc, x86_cpu_set, CPU_Undoc 330 noundoc, x86_cpu_clear, CPU_Undoc 331 undocumented, x86_cpu_set, CPU_Undoc 332 noundocumented, x86_cpu_clear, CPU_Undoc 333 obs, x86_cpu_set, CPU_Obs 334 noobs, x86_cpu_clear, CPU_Obs 335 obsolete, x86_cpu_set, CPU_Obs 336 noobsolete, x86_cpu_clear, CPU_Obs 337 priv, x86_cpu_set, CPU_Priv 338 nopriv, x86_cpu_clear, CPU_Priv 339 privileged, x86_cpu_set, CPU_Priv 340 noprivileged, x86_cpu_clear, CPU_Priv 341 svm, x86_cpu_set, CPU_SVM 342 nosvm, x86_cpu_clear, CPU_SVM 343 padlock, x86_cpu_set, CPU_PadLock 344 nopadlock, x86_cpu_clear, CPU_PadLock 345 em64t, x86_cpu_set, CPU_EM64T 346 noem64t, x86_cpu_clear, CPU_EM64T 347 ssse3, x86_cpu_set, CPU_SSSE3 348 nossse3, x86_cpu_clear, CPU_SSSE3 349 sse4.1, x86_cpu_set, CPU_SSE41 350 nosse4.1, x86_cpu_clear, CPU_SSE41 351 sse41, x86_cpu_set, CPU_SSE41 352 nosse41, x86_cpu_clear, CPU_SSE41 353 sse4.2, x86_cpu_set, CPU_SSE42 354 nosse4.2, x86_cpu_clear, CPU_SSE42 355 sse42, x86_cpu_set, CPU_SSE42 356 nosse42, x86_cpu_clear, CPU_SSE42 357 sse4a, x86_cpu_set, CPU_SSE4a 358 nosse4a, x86_cpu_clear, CPU_SSE4a 359 sse4, x86_cpu_set_sse4, 0 360 nosse4, x86_cpu_clear_sse4, 0 361 xsave, x86_cpu_set, CPU_XSAVE 362 noxsave, x86_cpu_clear, CPU_XSAVE 363 avx, x86_cpu_set, CPU_AVX 364 noavx, x86_cpu_clear, CPU_AVX 365 fma, x86_cpu_set, CPU_FMA 366 nofma, x86_cpu_clear, CPU_FMA 367 aes, x86_cpu_set, CPU_AES 368 noaes, x86_cpu_clear, CPU_AES 369 clmul, x86_cpu_set, CPU_CLMUL 370 noclmul, x86_cpu_clear, CPU_CLMUL 371 pclmulqdq, x86_cpu_set, CPU_CLMUL 372 nopclmulqdq, x86_cpu_clear, CPU_CLMUL 373 movbe, x86_cpu_set, CPU_MOVBE 374 nomovbe, x86_cpu_clear, CPU_MOVBE 375 xop, x86_cpu_set, CPU_XOP 376 noxop, x86_cpu_clear, CPU_XOP 377 fma4, x86_cpu_set, CPU_FMA4 378 nofma4, x86_cpu_clear, CPU_FMA4 379 f16c, x86_cpu_set, CPU_F16C 380 nof16c, x86_cpu_clear, CPU_F16C 381 fsgsbase, x86_cpu_set, CPU_FSGSBASE 382 nofsgsbase, x86_cpu_clear, CPU_FSGSBASE 383 rdrand, x86_cpu_set, CPU_RDRAND 384 nordrand, x86_cpu_clear, CPU_RDRAND 385 xsaveopt, x86_cpu_set, CPU_XSAVEOPT 386 noxsaveopt, x86_cpu_clear, CPU_XSAVEOPT 387 eptvpid, x86_cpu_set, CPU_EPTVPID 388 noeptvpid, x86_cpu_clear, CPU_EPTVPID 389 smx, x86_cpu_set, CPU_SMX 390 nosmx, x86_cpu_clear, CPU_SMX 391 avx2, x86_cpu_set, CPU_AVX2 392 noavx2, x86_cpu_clear, CPU_AVX2 393 bmi1, x86_cpu_set, CPU_BMI1 394 nobmi1, x86_cpu_clear, CPU_BMI1 395 bmi2, x86_cpu_set, CPU_BMI2 396 nobmi2, x86_cpu_clear, CPU_BMI2 397 invpcid, x86_cpu_set, CPU_INVPCID 398 noinvpcid, x86_cpu_clear, CPU_INVPCID 399 lzcnt, x86_cpu_set, CPU_LZCNT 400 nolzcnt, x86_cpu_clear, CPU_LZCNT 401 # Change NOP patterns 402 basicnop, x86_nop, X86_NOP_BASIC 403 intelnop, x86_nop, X86_NOP_INTEL 404 amdnop, x86_nop, X86_NOP_AMD 405 %% 406 407 void 408 yasm_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