add new sigc++2 directory
[ardour.git] / libs / soundtouch / cpu_detect_x86_gcc.cpp
1 ////////////////////////////////////////////////////////////////////////////////
2 ///
3 /// gcc version of the x86 CPU detect routine.
4 ///
5 /// This file is to be compiled on any platform with the GNU C compiler.
6 /// Compiler. Please see 'cpu_detect_x86_win.cpp' for the x86 Windows version 
7 /// of this file.
8 ///
9 /// Author        : Copyright (c) Olli Parviainen
10 /// Author e-mail : oparviai @ iki.fi
11 /// SoundTouch WWW: http://www.iki.fi/oparviai/soundtouch
12 ///
13 ////////////////////////////////////////////////////////////////////////////////
14 //
15 // Last changed  : $Date$
16 // File revision : $Revision$
17 //
18 // $Id$
19 //
20 ////////////////////////////////////////////////////////////////////////////////
21 //
22 // License :
23 //
24 //  SoundTouch audio processing library
25 //  Copyright (c) Olli Parviainen
26 //
27 //  This library is free software; you can redistribute it and/or
28 //  modify it under the terms of the GNU Lesser General Public
29 //  License as published by the Free Software Foundation; either
30 //  version 2.1 of the License, or (at your option) any later version.
31 //
32 //  This library is distributed in the hope that it will be useful,
33 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
34 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
35 //  Lesser General Public License for more details.
36 //
37 //  You should have received a copy of the GNU Lesser General Public
38 //  License along with this library; if not, write to the Free Software
39 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
40 //
41 ////////////////////////////////////////////////////////////////////////////////
42
43 #include <stdexcept>
44 #include <string>
45 #include "cpu_detect.h"
46
47 #ifndef __GNUC__
48 #error wrong platform - this source code file is for the GNU C compiler.
49 #endif
50
51 using namespace std;
52
53 #include <stdio.h>
54 //////////////////////////////////////////////////////////////////////////////
55 //
56 // processor instructions extension detection routines
57 //
58 //////////////////////////////////////////////////////////////////////////////
59
60
61 // Flag variable indicating whick ISA extensions are disabled (for debugging)
62 static uint _dwDisabledISA = 0x00;      // 0xffffffff; //<- use this to disable all extensions
63
64 // Disables given set of instruction extensions. See SUPPORT_... defines.
65 void disableExtensions(uint dwDisableMask)
66 {
67     _dwDisabledISA = dwDisableMask;
68 }
69
70
71
72 /// Checks which instruction set extensions are supported by the CPU.
73 uint detectCPUextensions(void)
74 {
75 #ifndef __i386__
76     return 0; // always disable extensions on non-x86 platforms.
77 #else
78     uint res = 0;
79
80     if (_dwDisabledISA == 0xffffffff) return 0;
81
82     asm volatile(
83         "\n\tpushl   %%ebx"              // store ebx
84         "\n\txor     %%esi, %%esi"       // clear %%esi = result register
85         // check if 'cpuid' instructions is available by toggling eflags bit 21
86
87         "\n\tpushf"                      // save eflags to stack
88         "\n\tpop     %%eax"              // load eax from stack (with eflags)
89         "\n\tmovl    %%eax, %%ecx"       // save the original eflags values to ecx
90         "\n\txor     $0x00200000, %%eax" // toggle bit 21
91         "\n\tpush    %%eax"              // store toggled eflags to stack
92         "\n\tpopf"                       // load eflags from stack
93         "\n\tpushf"                      // save updated eflags to stack
94         "\n\tpop     %%eax"              // load from stack
95         "\n\txor     %%edx, %%edx"       // clear edx for defaulting no mmx
96         "\n\tcmp     %%ecx, %%eax"       // compare to original eflags values
97         "\n\tjz      end"                // jumps to 'end' if cpuid not present
98
99         // cpuid instruction available, test for presence of mmx instructions
100
101         "\n\tmovl    $1, %%eax"
102         "\n\tcpuid"
103 //        movl       $0x00800000, %edx   // force enable MMX
104         "\n\ttest    $0x00800000, %%edx"
105         "\n\tjz      end"                // branch if MMX not available
106
107         "\n\tor      $0x01, %%esi"       // otherwise add MMX support bit
108
109         "\n\ttest    $0x02000000, %%edx"
110         "\n\tjz      test3DNow"          // branch if SSE not available
111
112         "\n\tor      $0x08, %%esi"       // otherwise add SSE support bit
113
114     "\n\ttest3DNow:"
115         // test for precense of AMD extensions
116         "\n\tmov     $0x80000000, %%eax"
117         "\n\tcpuid"
118         "\n\tcmp     $0x80000000, %%eax"
119         "\n\tjbe     end"                 // branch if no AMD extensions detected
120
121         // test for precense of 3DNow! extension
122         "\n\tmov     $0x80000001, %%eax"
123         "\n\tcpuid"
124         "\n\ttest    $0x80000000, %%edx"
125         "\n\tjz      end"                  // branch if 3DNow! not detected
126
127         "\n\tor      $0x02, %%esi"         // otherwise add 3DNow support bit
128
129     "\n\tend:"
130
131         "\n\tmov     %%esi, %0"
132         "\n\tpopl    %%ebx"
133
134       : "=r" (res)
135       : /* no inputs */
136       : "%edx", "%eax", "%ecx", "%esi" );
137       
138     return res & ~_dwDisabledISA;
139 #endif
140 }