|
1 //////////////////////////////////////////////////////////////////////////////// |
|
2 /// |
|
3 /// Generic version of the x86 CPU extension detection routine. |
|
4 /// |
|
5 /// This file is for GNU & other non-Windows compilers, see 'cpu_detect_x86_win.cpp' |
|
6 /// for the Microsoft compiler version. |
|
7 /// |
|
8 /// Author : Copyright (c) Olli Parviainen |
|
9 /// Author e-mail : oparviai 'at' iki.fi |
|
10 /// SoundTouch WWW: http://www.surina.net/soundtouch |
|
11 /// |
|
12 //////////////////////////////////////////////////////////////////////////////// |
|
13 // |
|
14 // Last changed : $Date: 2014-01-07 12:24:28 -0600 (Tue, 07 Jan 2014) $ |
|
15 // File revision : $Revision: 4 $ |
|
16 // |
|
17 // $Id: cpu_detect_x86.cpp 183 2014-01-07 18:24:28Z oparviai $ |
|
18 // |
|
19 //////////////////////////////////////////////////////////////////////////////// |
|
20 // |
|
21 // License : |
|
22 // |
|
23 // SoundTouch audio processing library |
|
24 // Copyright (c) Olli Parviainen |
|
25 // |
|
26 // This library is free software; you can redistribute it and/or |
|
27 // modify it under the terms of the GNU Lesser General Public |
|
28 // License as published by the Free Software Foundation; either |
|
29 // version 2.1 of the License, or (at your option) any later version. |
|
30 // |
|
31 // This library is distributed in the hope that it will be useful, |
|
32 // but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
33 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
34 // Lesser General Public License for more details. |
|
35 // |
|
36 // You should have received a copy of the GNU Lesser General Public |
|
37 // License along with this library; if not, write to the Free Software |
|
38 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
39 // |
|
40 //////////////////////////////////////////////////////////////////////////////// |
|
41 |
|
42 #include "cpu_detect.h" |
|
43 #include "STTypes.h" |
|
44 |
|
45 |
|
46 #if defined(SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS) |
|
47 #if defined(__GNUC__) && defined(HAVE_CPUID_H) |
|
48 // gcc and clang |
|
49 #include "cpuid.h" |
|
50 #elif defined(_M_IX86) |
|
51 // windows non-gcc |
|
52 #include <intrin.h> |
|
53 #endif |
|
54 |
|
55 #define bit_MMX (1 << 23) |
|
56 #define bit_SSE (1 << 25) |
|
57 #define bit_SSE2 (1 << 26) |
|
58 #endif |
|
59 |
|
60 |
|
61 ////////////////////////////////////////////////////////////////////////////// |
|
62 // |
|
63 // processor instructions extension detection routines |
|
64 // |
|
65 ////////////////////////////////////////////////////////////////////////////// |
|
66 |
|
67 // Flag variable indicating whick ISA extensions are disabled (for debugging) |
|
68 static uint _dwDisabledISA = 0x00; // 0xffffffff; //<- use this to disable all extensions |
|
69 |
|
70 // Disables given set of instruction extensions. See SUPPORT_... defines. |
|
71 void disableExtensions(uint dwDisableMask) |
|
72 { |
|
73 _dwDisabledISA = dwDisableMask; |
|
74 } |
|
75 |
|
76 |
|
77 |
|
78 /// Checks which instruction set extensions are supported by the CPU. |
|
79 uint detectCPUextensions(void) |
|
80 { |
|
81 /// If building for a 64bit system (no Itanium) and the user wants optimizations. |
|
82 /// Return the OR of SUPPORT_{MMX,SSE,SSE2}. 11001 or 0x19. |
|
83 /// Keep the _dwDisabledISA test (2 more operations, could be eliminated). |
|
84 #if ((defined(__GNUC__) && defined(__x86_64__)) \ |
|
85 || defined(_M_X64)) \ |
|
86 && defined(SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS) |
|
87 return 0x19 & ~_dwDisabledISA; |
|
88 |
|
89 /// If building for a 32bit system and the user wants optimizations. |
|
90 /// Keep the _dwDisabledISA test (2 more operations, could be eliminated). |
|
91 #elif ((defined(__GNUC__) && defined(__i386__)) \ |
|
92 || defined(_M_IX86)) \ |
|
93 && defined(SOUNDTOUCH_ALLOW_X86_OPTIMIZATIONS) |
|
94 |
|
95 if (_dwDisabledISA == 0xffffffff) return 0; |
|
96 |
|
97 uint res = 0; |
|
98 |
|
99 #if !defined(__GNUC__) |
|
100 // Window / VS version of cpuid. Notice that Visual Studio 2005 or later required |
|
101 // for __cpuid intrinsic support. |
|
102 int reg[4] = {-1}; |
|
103 |
|
104 // Check if no cpuid support. |
|
105 __cpuid(reg,0); |
|
106 if ((unsigned int)reg[0] == 0) return 0; // always disable extensions. |
|
107 |
|
108 __cpuid(reg,1); |
|
109 if ((unsigned int)reg[3] & bit_MMX) res = res | SUPPORT_MMX; |
|
110 if ((unsigned int)reg[3] & bit_SSE) res = res | SUPPORT_SSE; |
|
111 if ((unsigned int)reg[3] & bit_SSE2) res = res | SUPPORT_SSE2; |
|
112 #elif defined(HAVE_CPUID_H) |
|
113 // GCC version of cpuid. Requires GCC 4.3.0 or later for __cpuid intrinsic support. |
|
114 uint eax, ebx, ecx, edx; // unsigned int is the standard type. uint is defined by the compiler and not guaranteed to be portable. |
|
115 |
|
116 // Check if no cpuid support. |
|
117 if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx)) return 0; // always disable extensions. |
|
118 |
|
119 if (edx & bit_MMX) res = res | SUPPORT_MMX; |
|
120 if (edx & bit_SSE) res = res | SUPPORT_SSE; |
|
121 if (edx & bit_SSE2) res = res | SUPPORT_SSE2; |
|
122 #else |
|
123 // Compatible with GCC but no cpuid.h. |
|
124 return 0; |
|
125 #endif |
|
126 |
|
127 return res & ~_dwDisabledISA; |
|
128 |
|
129 #else |
|
130 |
|
131 /// One of these is true: |
|
132 /// 1) We don't want optimizations. |
|
133 /// 2) Using an unsupported compiler. |
|
134 /// 3) Running on a non-x86 platform. |
|
135 return 0; |
|
136 |
|
137 #endif |
|
138 } |