source: trunk/lib/x86_CPU_detect.h @ 395

Last change on this file since 395 was 395, checked in by cameron, 9 years ago

Add compile-time detection of x86 and x86-64 compilation targets.

File size: 4.0 KB
Line 
1/*  x86_CPU_detect.h:  Run-Time Detection of x86 and x86_64 SIMD features.
2 
3    Copyright (C) 2010, Robert D. Cameron
4    Licensed to the public under Academic Free License version 3.0.
5
6This file defines the following functions which perform
7runtime tests to see if particular SIMD or other acceleration
8features are supported on x86 and x86-64 architectures.
9The functions return 0 if a feature is not supported, a nonzero value,
10otherwise.
11
12CPU_has_MMX()
13CPU_has_SSE()
14CPU_has_SSE2()
15CPU_has_SSE3()
16CPU_has_SSSE3()
17CPU_has_SSE41()
18CPU_has_SSE42()
19CPU_has_AVX()
20CPU_has_POPCOUNT()
21
22The CPUID instruction is used to determine these features,
23taking advantage of the appropriate __cpuid compiler intrinsic
24available with GCC and MSVC compilers.
25
26*/
27
28#ifndef X86_CPU_DETECT_H
29#define X86_CPU_DETECT_H
30
31/*  These routines are for the Intel/AMD x86 (32-bit) and x86-64 (64-bit)
32    architectures.  Ensure that we are compiling for one of these
33    architectures.  Define common macros x86_32 and x86_64 based on
34    known compiler-specific macros for these architectures.
35    See http://predef.sourceforge.net/prearch.html
36*/
37
38#if defined(__x86_64__) || defined(_M_X86_64)
39#define x86_64 1
40#elif (defined(__i386__) || defined(_M_IX86) || defined(__i386) || defined(__THW_INTEL__)
41#define x86_32 1
42#endif
43
44#if defined(x86_32) || defined(x86_64)
45
46enum CPUid_reg {
47  reg_eax = 0, 
48  reg_ebx = 1, 
49  reg_ecx = 2, 
50  reg_edx = 3
51};
52
53#ifdef _MSC_VER
54#include <intrin.h>
55static inline int check_CPUid1_feature(CPUid_reg reg, int CPUid_bit) {
56  int CPUinfo[4];
57  __cpuid(CPUinfo, 1);
58  return CPUInfo[reg] & CPUid_bit;
59}
60#endif
61
62#ifdef __GNUC__
63#include <cpuid.h>
64static inline int check_CPUid1_feature(CPUid_reg reg, int CPUid_bit) {
65  int CPUinfo[4];
66  if __get_cpuid(1, &CPUinfo[reg_eax], &CPUinfo[reg_ebx], &CPUinfo[reg_ecx], &CPUinfo[reg_edx]) {
67    return CPUInfo[reg] & CPUid_bit;
68  else return 0;
69}
70#endif
71
72
73#define MMX_CPUid_feature_register reg_edx
74#define MMX_CPUid_feature_bit (1 << 23)
75
76#define SSE_CPUid_feature_register reg_edx
77#define SSE_CPUid_feature_bit (1 << 25)
78
79#define SSE2_CPUid_feature_register reg_edx
80#define SSE2_CPUid_feature_bit (1 << 26)
81
82#define SSE3_CPUid_feature_register reg_ecx
83#define SSE3_CPUid_feature_bit (1 << 0)
84
85#define SSSE3_CPUid_feature_register reg_ecx
86#define SSSE3_CPUid_feature_bit (1 << 9)
87
88#define SSE41_CPUid_feature_register reg_ecx
89#define SSE41_CPUid_feature_bit (1 << 19)
90
91#define SSE42_CPUid_feature_register reg_ecx
92#define SSE42_CPUid_feature_bit (1 << 20)
93
94#define AVX_CPUid_feature_register reg_ecx
95#define AVX_CPUid_feature_bit (1 << 28)
96
97#define POPCOUNT_CPUid_feature_register reg_ecx
98#define POPCOUNT_CPUid_feature_bit (1 << 23)
99
100
101static inline int CPU_has_MMX() {
102#ifdef x86_64
103  return MMX_CPUid_feature_bit;  /*  MMX always available on x86_64 */
104#else
105  return check_CPUid1_feature(MMX_CPUid_feature_register, MMX_CPUid_feature_bit);
106#endif
107}
108static inline int CPU_has_SSE() {
109#ifdef x86_64
110  return SSE_CPUid_feature_bit;  /*  SSE always available on x86_64 */
111#else
112  return check_CPUid1_feature(SSE_CPUid_feature_register, SSE_CPUid_feature_bit);
113#endif
114}
115static inline int CPU_has_SSE2() {
116#ifdef x86_64
117  return SSE2_CPUid_feature_bit;  /*  SSE2 always available on x86_64 */
118#else
119  return check_CPUid1_feature(SSE2_CPUid_feature_register, SSE2_CPUid_feature_bit);
120#endif
121}
122
123static inline int CPU_has_SSE3() {
124  return check_CPUid1_feature(SSE3_CPUid_feature_register, SSE3_CPUid_feature_bit);
125}
126
127static inline int CPU_has_SSSE3() {
128  return check_CPUid1_feature(SSSE3_CPUid_feature_register, SSSE3_CPUid_feature_bit);
129}
130
131static inline int CPU_has_SSE41() {
132  return check_CPUid1_feature(SSE41_CPUid_feature_register, SSE41_CPUid_feature_bit);
133}
134
135static inline int CPU_has_SSE42() {
136  return check_CPUid1_feature(SSE42_CPUid_feature_register, SSE42_CPUid_feature_bit);
137}
138
139static inline int CPU_has_AVX() {
140  return check_CPUid1_feature(AVX_CPUid_feature_register, AVX_CPUid_feature_bit);
141}
142
143static inline int CPU_has_POPCOUNT() {
144  return check_CPUid1_feature(POPCOUNT_CPUid_feature_register, POPCOUNT_CPUid_feature_bit);
145}
146
147#endif
148#endif
Note: See TracBrowser for help on using the repository browser.