• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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