# # x86 CPU recognition # # Copyright (C) 2002-2007 Peter Johnson # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. %{ #include #include #include #include #include "modules/arch/x86/x86arch.h" #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 #define PROC_westmere 14 #define PROC_sandybridge 15 #define PROC_ivybridge 16 #define PROC_haswell 17 #define PROC_broadwell 18 #define PROC_skylake 19 static void x86_cpu_intel(wordptr cpu, yasm_arch_x86 *arch_x86, 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_skylake) { BitVector_Bit_On(cpu, CPU_SHA); } if (data >= PROC_broadwell) { BitVector_Bit_On(cpu, CPU_RDSEED); BitVector_Bit_On(cpu, CPU_ADX); BitVector_Bit_On(cpu, CPU_PRFCHW); } if (data >= PROC_haswell) { BitVector_Bit_On(cpu, CPU_FMA); BitVector_Bit_On(cpu, CPU_AVX2); BitVector_Bit_On(cpu, CPU_BMI1); BitVector_Bit_On(cpu, CPU_BMI2); BitVector_Bit_On(cpu, CPU_INVPCID); BitVector_Bit_On(cpu, CPU_LZCNT); BitVector_Bit_On(cpu, CPU_TSX); BitVector_Bit_On(cpu, CPU_SMAP); } if (data >= PROC_ivybridge) { BitVector_Bit_On(cpu, CPU_F16C); BitVector_Bit_On(cpu, CPU_FSGSBASE); BitVector_Bit_On(cpu, CPU_RDRAND); } if (data >= PROC_sandybridge) { BitVector_Bit_On(cpu, CPU_AVX); BitVector_Bit_On(cpu, CPU_XSAVEOPT); BitVector_Bit_On(cpu, CPU_EPTVPID); BitVector_Bit_On(cpu, CPU_SMX); } if (data >= PROC_westmere) { BitVector_Bit_On(cpu, CPU_AES); BitVector_Bit_On(cpu, CPU_CLMUL); } if (data >= PROC_nehalem) { BitVector_Bit_On(cpu, CPU_SSE42); BitVector_Bit_On(cpu, CPU_XSAVE); } 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); /* Use Intel long NOPs if 686 or better */ if (data >= PROC_686) arch_x86->nop = X86_NOP_INTEL; else arch_x86->nop = X86_NOP_BASIC; } static void x86_cpu_ia64(wordptr cpu, yasm_arch_x86 *arch_x86, 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_bulldozer 11 #define PROC_k10 10 #define PROC_venice 9 #define PROC_hammer 8 #define PROC_k7 7 #define PROC_k6 6 static void x86_cpu_amd(wordptr cpu, yasm_arch_x86 *arch_x86, 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_bulldozer) { BitVector_Bit_On(cpu, CPU_XOP); BitVector_Bit_On(cpu, CPU_FMA4); } if (data >= PROC_k10) BitVector_Bit_On(cpu, CPU_SSE4a); if (data >= PROC_venice) BitVector_Bit_On(cpu, CPU_SSE3); 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); /* Use AMD long NOPs if k6 or better */ if (data >= PROC_k6) arch_x86->nop = X86_NOP_AMD; else arch_x86->nop = X86_NOP_BASIC; } static void x86_cpu_set(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data) { BitVector_Bit_On(cpu, data); } static void x86_cpu_clear(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data) { BitVector_Bit_Off(cpu, data); } static void x86_cpu_set_sse4(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data) { BitVector_Bit_On(cpu, CPU_SSE41); BitVector_Bit_On(cpu, CPU_SSE42); } static void x86_cpu_clear_sse4(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data) { BitVector_Bit_Off(cpu, CPU_SSE41); BitVector_Bit_Off(cpu, CPU_SSE42); } static void x86_nop(wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data) { arch_x86->nop = data; } %} %ignore-case %language=ANSI-C %compare-strncmp %readonly-tables %enum %struct-type %define hash-function-name cpu_hash %define lookup-function-name cpu_find struct cpu_parse_data { const char *name; void (*handler) (wordptr cpu, yasm_arch_x86 *arch_x86, unsigned int data); unsigned int data; }; %% 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 k8, x86_cpu_amd, PROC_hammer hammer, x86_cpu_amd, PROC_hammer clawhammer, x86_cpu_amd, PROC_hammer opteron, x86_cpu_amd, PROC_hammer athlon64, x86_cpu_amd, PROC_hammer athlon-64, x86_cpu_amd, PROC_hammer venice, x86_cpu_amd, PROC_venice k10, x86_cpu_amd, PROC_k10 phenom, x86_cpu_amd, PROC_k10 family10h, x86_cpu_amd, PROC_k10 bulldozer, x86_cpu_amd, PROC_bulldozer prescott, x86_cpu_intel, PROC_prescott conroe, x86_cpu_intel, PROC_conroe core2, x86_cpu_intel, PROC_conroe penryn, x86_cpu_intel, PROC_penryn nehalem, x86_cpu_intel, PROC_nehalem corei7, x86_cpu_intel, PROC_nehalem westmere, x86_cpu_intel, PROC_westmere sandybridge, x86_cpu_intel, PROC_sandybridge ivybridge, x86_cpu_intel, PROC_ivybridge haswell, x86_cpu_intel, PROC_haswell broadwell, x86_cpu_intel, PROC_broadwell skylake, x86_cpu_intel, PROC_skylake # # Features have "no" versions to disable them, and only set/reset the # specific feature being changed. All other bits are left alone. # 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 sse41, x86_cpu_set, CPU_SSE41 nosse41, x86_cpu_clear, CPU_SSE41 sse4.2, x86_cpu_set, CPU_SSE42 nosse4.2, x86_cpu_clear, CPU_SSE42 sse42, x86_cpu_set, CPU_SSE42 nosse42, x86_cpu_clear, CPU_SSE42 sse4a, x86_cpu_set, CPU_SSE4a nosse4a, x86_cpu_clear, CPU_SSE4a sse4, x86_cpu_set_sse4, 0 nosse4, x86_cpu_clear_sse4, 0 xsave, x86_cpu_set, CPU_XSAVE noxsave, x86_cpu_clear, CPU_XSAVE avx, x86_cpu_set, CPU_AVX noavx, x86_cpu_clear, CPU_AVX fma, x86_cpu_set, CPU_FMA nofma, x86_cpu_clear, CPU_FMA aes, x86_cpu_set, CPU_AES noaes, x86_cpu_clear, CPU_AES clmul, x86_cpu_set, CPU_CLMUL noclmul, x86_cpu_clear, CPU_CLMUL pclmulqdq, x86_cpu_set, CPU_CLMUL nopclmulqdq, x86_cpu_clear, CPU_CLMUL movbe, x86_cpu_set, CPU_MOVBE nomovbe, x86_cpu_clear, CPU_MOVBE xop, x86_cpu_set, CPU_XOP noxop, x86_cpu_clear, CPU_XOP fma4, x86_cpu_set, CPU_FMA4 nofma4, x86_cpu_clear, CPU_FMA4 f16c, x86_cpu_set, CPU_F16C nof16c, x86_cpu_clear, CPU_F16C fsgsbase, x86_cpu_set, CPU_FSGSBASE nofsgsbase, x86_cpu_clear, CPU_FSGSBASE rdrand, x86_cpu_set, CPU_RDRAND nordrand, x86_cpu_clear, CPU_RDRAND xsaveopt, x86_cpu_set, CPU_XSAVEOPT noxsaveopt, x86_cpu_clear, CPU_XSAVEOPT eptvpid, x86_cpu_set, CPU_EPTVPID noeptvpid, x86_cpu_clear, CPU_EPTVPID smx, x86_cpu_set, CPU_SMX nosmx, x86_cpu_clear, CPU_SMX avx2, x86_cpu_set, CPU_AVX2 noavx2, x86_cpu_clear, CPU_AVX2 tsx, x86_cpu_set, CPU_TSX notsx, x86_cpu_clear, CPU_TSX bmi1, x86_cpu_set, CPU_BMI1 nobmi1, x86_cpu_clear, CPU_BMI1 bmi2, x86_cpu_set, CPU_BMI2 nobmi2, x86_cpu_clear, CPU_BMI2 invpcid, x86_cpu_set, CPU_INVPCID noinvpcid, x86_cpu_clear, CPU_INVPCID lzcnt, x86_cpu_set, CPU_LZCNT nolzcnt, x86_cpu_clear, CPU_LZCNT tbm, x86_cpu_set, CPU_TBM notbm, x86_cpu_clear, CPU_TBM sha, x86_cpu_set, CPU_SHA nosha, x86_cpu_clear, CPU_SHA smap, x86_cpu_set, CPU_SMAP nosmap, x86_cpu_clear, CPU_SMAP rdseed, x86_cpu_set, CPU_RDSEED nordseed, x86_cpu_clear, CPU_RDSEED adx, x86_cpu_set, CPU_ADX noadx, x86_cpu_clear, CPU_ADX prfchw, x86_cpu_set, CPU_PRFCHW noprfchw, x86_cpu_clear, CPU_PRFCHW # Change NOP patterns basicnop, x86_nop, X86_NOP_BASIC intelnop, x86_nop, X86_NOP_INTEL amdnop, x86_nop, X86_NOP_AMD %% void 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; size_t i; static char lcaseid[16]; if (cpuid_len > 15) return; for (i=0; icpu_enables[arch_x86->active_cpu]); pdata->handler(new_cpu, arch_x86, 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; }