Line data Source code
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 18:24:28 +0000 (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 0 : void disableExtensions(uint dwDisableMask)
72 : {
73 0 : _dwDisabledISA = dwDisableMask;
74 0 : }
75 :
76 :
77 :
78 : /// Checks which instruction set extensions are supported by the CPU.
79 0 : 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 0 : 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 : }
|