source: contrib/API/lib/cputest.c

Last change on this file was 541, checked in by David Azarewicz, 15 years ago

Initial import

File size: 4.4 KB
Line 
1/*
2 * Cpu detection code, extracted from mmx.h ((c)1997-99 by H. Dietz
3 * and R. Fisher). Converted to C and improved by Fabrice Bellard
4 *
5 * This file is part of uniaud.dll.
6 *
7 * Copyright (c) 2010 Mensys BV
8 * Copyright (c) 2007 Vlad Stelmahovsky aka Vladest
9 *
10 * This library is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as
12 * published by the Free Software Foundation, either version 3 of
13 * the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License and the GNU General Public License along with this library.
22 * If not, see <http://www.gnu.org/licenses/>.
23 */
24
25#include <stdlib.h>
26//#include "../dsputil.h"
27#define MM_MMX 0x0001 /* standard MMX */
28#define MM_3DNOW 0x0004 /* AMD 3DNOW */
29#define MM_MMXEXT 0x0002 /* SSE integer functions or AMD MMX ext */
30#define MM_SSE 0x0008 /* SSE functions */
31#define MM_SSE2 0x0010 /* PIV SSE2 functions */
32
33
34/* ebx saving is necessary for PIC. gcc seems unable to see it alone */
35
36/* Function to test if multimedia instructions are supported... */
37int mm_support(void)
38{
39 int rval;
40 int Reax, Rebx, Recx, Redx;
41
42#pragma disable_message (200)
43void cpuid(unsigned long index);
44#pragma aux cpuid = \
45 "mov esi, ebx" \
46 "cpuid" \
47 "xchg esi, ebx" \
48 "mov Reax, eax" \
49 "mov Rebx, esi" \
50 "mov Recx, ecx" \
51 "mov Redx, edx" \
52 parm [eax] \
53 modify [eax ebx ecx edx esi]
54
55 _asm {
56 /* See if CPUID instruction is supported ... */
57 /* ... Get copies of EFLAGS into eax and ecx */
58 pushfd
59 pop eax
60 mov Recx, eax
61
62 /* ... Toggle the ID bit in one copy and store */
63 /* to the EFLAGS reg */
64 xor eax, 0x00200000
65 push eax
66 popfd
67
68 /* ... Get the (hopefully modified) EFLAGS */
69 pushfd
70 pop Reax
71 }
72
73 if (Reax == Recx) return 0; /* CPUID not supported */
74
75 cpuid(0);
76
77 if (Rebx == 0x756e6547 &&
78 Redx == 0x49656e69 &&
79 Recx == 0x6c65746e) {
80
81 /* intel */
82 inteltest:
83 cpuid(1);
84 if ((Redx & 0x00800000) == 0) return 0;
85 rval = MM_MMX;
86 if (Redx & 0x02000000) rval |= MM_MMXEXT | MM_SSE;
87 if (Redx & 0x04000000) rval |= MM_SSE2;
88 return rval;
89 } else if (Rebx == 0x68747541 &&
90 Redx == 0x69746e65 &&
91 Recx == 0x444d4163) {
92 /* AMD */
93 cpuid(0x80000000);
94 if ((unsigned)Reax < 0x80000001) goto inteltest;
95 cpuid(0x80000001);
96 if ((Redx & 0x00800000) == 0) return 0;
97 rval = MM_MMX;
98 if (Redx & 0x80000000) rval |= MM_3DNOW;
99 if (Redx & 0x00400000) rval |= MM_MMXEXT;
100 return rval;
101 } else if (Rebx == 0x746e6543 &&
102 Redx == 0x48727561 &&
103 Recx == 0x736c7561) { /* "CentaurHauls" */
104 /* VIA C3 */
105 cpuid(0x80000000);
106 if ((unsigned)Reax < 0x80000001) goto inteltest;
107 cpuid(0x80000001);
108 rval = 0;
109 if( Redx & ( 1 << 31) ) rval |= MM_3DNOW;
110 if( Redx & ( 1 << 23) ) rval |= MM_MMX;
111 if( Redx & ( 1 << 24) ) rval |= MM_MMXEXT;
112 return rval;
113 } else if (Rebx == 0x69727943 &&
114 Redx == 0x736e4978 &&
115 Recx == 0x64616574) {
116 /* Cyrix Section */
117 /* See if extended CPUID level 80000001 is supported */
118 /* The value of CPUID/80000001 for the 6x86MX is undefined
119 according to the Cyrix CPU Detection Guide (Preliminary
120 Rev. 1.01 table 1), so we'll check the value of eax for
121 CPUID/0 to see if standard CPUID level 2 is supported.
122 According to the table, the only CPU which supports level
123 2 is also the only one which supports extended CPUID levels.
124 */
125 if (Reax != 2) goto inteltest;
126 cpuid(0x80000001);
127 if ((Reax & 0x00800000) == 0) return 0;
128 rval = MM_MMX;
129 if (Reax & 0x01000000) rval |= MM_MMXEXT;
130 return rval;
131 } else {
132 return 0;
133 }
134}
135#pragma enable_message (200)
136
137#ifdef __TEST__
138int main ( void )
139{
140 int mm_flags;
141 mm_flags = mm_support();
142 printf("mm_support = 0x%08u\n",mm_flags);
143 return 0;
144}
145#endif
Note: See TracBrowser for help on using the repository browser.