5
|
1 /*
|
|
2 * SpanDSP - a series of DSP components for telephony
|
|
3 *
|
|
4 * testcpuid.c - Check the CPU type, to identify special features, like SSE.
|
|
5 *
|
|
6 * Written by Steve Underwood <steveu@coppice.org>
|
|
7 * Stitched together from bits of testing code found here and there
|
|
8 *
|
|
9 * Copyright (C) 2004 Steve Underwood
|
|
10 *
|
|
11 * All rights reserved.
|
|
12 *
|
|
13 * This program is free software; you can redistribute it and/or modify
|
|
14 * it under the terms of the GNU General Public License version 2, as
|
|
15 * published by the Free Software Foundation.
|
|
16 *
|
|
17 * This program is distributed in the hope that it will be useful,
|
|
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
20 * GNU General Public License for more details.
|
|
21 *
|
|
22 * You should have received a copy of the GNU General Public License
|
|
23 * along with this program; if not, write to the Free Software
|
|
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
25 *
|
|
26 * $Id: testcpuid.c,v 1.9 2006/10/24 13:45:27 steveu Exp $
|
|
27 */
|
|
28
|
|
29 /*! \file */
|
|
30
|
|
31 #ifdef HAVE_CONFIG_H
|
|
32 #include <config.h>
|
|
33 #endif
|
|
34
|
|
35 #include <inttypes.h>
|
|
36
|
|
37 /* Make this file just disappear if we are not on an x86 machine */
|
|
38 #if defined(__i386__) // || defined(__x86_64__)
|
|
39
|
|
40 #define X86_EFLAGS_CF 0x00000001 /* Carry Flag */
|
|
41 #define X86_EFLAGS_PF 0x00000004 /* Parity Flag */
|
|
42 #define X86_EFLAGS_AF 0x00000010 /* Auxillary carry Flag */
|
|
43 #define X86_EFLAGS_ZF 0x00000040 /* Zero Flag */
|
|
44 #define X86_EFLAGS_SF 0x00000080 /* Sign Flag */
|
|
45 #define X86_EFLAGS_TF 0x00000100 /* Trap Flag */
|
|
46 #define X86_EFLAGS_IF 0x00000200 /* Interrupt Flag */
|
|
47 #define X86_EFLAGS_DF 0x00000400 /* Direction Flag */
|
|
48 #define X86_EFLAGS_OF 0x00000800 /* Overflow Flag */
|
|
49 #define X86_EFLAGS_IOPL 0x00003000 /* IOPL mask */
|
|
50 #define X86_EFLAGS_NT 0x00004000 /* Nested Task */
|
|
51 #define X86_EFLAGS_RF 0x00010000 /* Resume Flag */
|
|
52 #define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */
|
|
53 #define X86_EFLAGS_AC 0x00040000 /* Alignment Check */
|
|
54 #define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */
|
|
55 #define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */
|
|
56 #define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */
|
|
57
|
|
58 /* Standard macro to see if a specific flag is changeable */
|
|
59 static __inline__ int flag_is_changeable_p(uint32_t flag)
|
|
60 {
|
|
61 uint32_t f1;
|
|
62 uint32_t f2;
|
|
63
|
|
64 __asm__ __volatile__ (
|
|
65 " pushfl\n"
|
|
66 " pushfl\n"
|
|
67 " popl %0\n"
|
|
68 " movl %0,%1\n"
|
|
69 " xorl %2,%0\n"
|
|
70 " pushl %0\n"
|
|
71 " popfl\n"
|
|
72 " pushfl\n"
|
|
73 " popl %0\n"
|
|
74 " popfl\n"
|
|
75 : "=&r" (f1), "=&r" (f2)
|
|
76 : "ir" (flag));
|
|
77
|
|
78 return ((f1^f2) & flag) != 0;
|
|
79 }
|
|
80 /*- End of function --------------------------------------------------------*/
|
|
81
|
|
82 /* Probe for the CPUID instruction */
|
|
83 static int have_cpuid_p(void)
|
|
84 {
|
|
85 return flag_is_changeable_p(X86_EFLAGS_ID);
|
|
86 }
|
|
87 /*- End of function --------------------------------------------------------*/
|
|
88
|
|
89 int has_MMX(void)
|
|
90 {
|
|
91 int result;
|
|
92
|
|
93 if (!have_cpuid_p())
|
|
94 return 0;
|
|
95 /*endif*/
|
|
96 __asm__ __volatile__ (
|
|
97 " push %%ebx;\n"
|
|
98 " mov $1,%%eax;\n"
|
|
99 " cpuid;\n"
|
|
100 " xor %%eax,%%eax;\n"
|
|
101 " test $0x800000,%%edx;\n"
|
|
102 " jz 1f;\n" /* no MMX support */
|
|
103 " inc %%eax;\n" /* MMX support */
|
|
104 "1:\n"
|
|
105 " pop %%ebx;\n"
|
|
106 : "=a" (result)
|
|
107 :
|
|
108 : "ecx", "edx");
|
|
109 return result;
|
|
110 }
|
|
111 /*- End of function --------------------------------------------------------*/
|
|
112
|
|
113 int has_SIMD(void)
|
|
114 {
|
|
115 int result;
|
|
116
|
|
117 if (!have_cpuid_p())
|
|
118 return 0;
|
|
119 /*endif*/
|
|
120 __asm__ __volatile__ (
|
|
121 " push %%ebx;\n"
|
|
122 " mov $1,%%eax;\n"
|
|
123 " cpuid;\n"
|
|
124 " xor %%eax,%%eax;\n"
|
|
125 " test $0x02000000,%%edx;\n"
|
|
126 " jz 1f;\n" /* no SIMD support */
|
|
127 " inc %%eax;\n" /* SIMD support */
|
|
128 "1:\n"
|
|
129 " pop %%ebx;\n"
|
|
130 : "=a" (result)
|
|
131 :
|
|
132 : "ecx", "edx");
|
|
133 return result;
|
|
134 }
|
|
135 /*- End of function --------------------------------------------------------*/
|
|
136
|
|
137 int has_SIMD2(void)
|
|
138 {
|
|
139 int result;
|
|
140
|
|
141 if (!have_cpuid_p())
|
|
142 return 0;
|
|
143 /*endif*/
|
|
144 __asm__ __volatile__ (
|
|
145 " push %%ebx;\n"
|
|
146 " mov $1,%%eax;\n"
|
|
147 " cpuid;\n"
|
|
148 " xor %%eax,%%eax;\n"
|
|
149 " test $0x04000000,%%edx;\n"
|
|
150 " jz 1f;\n" /* no SIMD2 support */
|
|
151 " inc %%eax;\n" /* SIMD2 support */
|
|
152 "1:\n"
|
|
153 " pop %%ebx;\n"
|
|
154 : "=a" (result)
|
|
155 :
|
|
156 : "ecx", "edx");
|
|
157 return result;
|
|
158 }
|
|
159 /*- End of function --------------------------------------------------------*/
|
|
160
|
|
161 int has_3DNow(void)
|
|
162 {
|
|
163 int result;
|
|
164
|
|
165 if (!have_cpuid_p())
|
|
166 return 0;
|
|
167 /*endif*/
|
|
168 __asm__ __volatile__ (
|
|
169 " push %%ebx;\n"
|
|
170 " mov $0x80000000,%%eax;\n"
|
|
171 " cpuid;\n"
|
|
172 " xor %%ecx,%%ecx;\n"
|
|
173 " cmp $0x80000000,%%eax;\n"
|
|
174 " jbe 1f;\n" /* no extended MSR(1), so no 3DNow! */
|
|
175 " mov $0x80000001,%%eax;\n"
|
|
176 " cpuid;\n"
|
|
177 " xor %%ecx,%%ecx;\n"
|
|
178 " test $0x80000000,%%edx;\n"
|
|
179 " jz 1f;\n" /* no 3DNow! support */
|
|
180 " inc %%ecx;\n" /* 3DNow! support */
|
|
181 "1:\n"
|
|
182 " pop %%ebx;\n"
|
|
183 : "=c" (result)
|
|
184 :
|
|
185 : "eax", "edx");
|
|
186 return result;
|
|
187 }
|
|
188 /*- End of function --------------------------------------------------------*/
|
|
189
|
|
190 #if defined(TESTBED)
|
|
191 int main(int argc, char *argv[])
|
|
192 {
|
|
193 int result;
|
|
194
|
|
195 result = has_MMX();
|
|
196 printf("MMX is %x\n", result);
|
|
197 result = has_SIMD();
|
|
198 printf("SIMD is %x\n", result);
|
|
199 result = has_SIMD2();
|
|
200 printf("SIMD2 is %x\n", result);
|
|
201 result = has_3DNow();
|
|
202 printf("3DNow is %x\n", result);
|
|
203 return 0;
|
|
204 }
|
|
205 /*- End of function --------------------------------------------------------*/
|
|
206 #endif
|
|
207
|
|
208 #endif
|
|
209 /*- End of file ------------------------------------------------------------*/
|