Home | History | Annotate | Download | only in x86
      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