Mercurial > sdl-ios-xcode
comparison src/cpuinfo/SDL_cpuinfo.c @ 785:ca06a994f03c
Fixed bugs in CPU feature detection and added extended feature detection
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 24 Jan 2004 05:47:19 +0000 |
parents | a2dde6aff60e |
children | e1e0a0a94570 |
comparison
equal
deleted
inserted
replaced
784:a2dde6aff60e | 785:ca06a994f03c |
---|---|
34 #include <sys/sysctl.h> /* For AltiVec check */ | 34 #include <sys/sysctl.h> /* For AltiVec check */ |
35 #endif | 35 #endif |
36 | 36 |
37 #define CPU_HAS_RDTSC 0x00000001 | 37 #define CPU_HAS_RDTSC 0x00000001 |
38 #define CPU_HAS_MMX 0x00000002 | 38 #define CPU_HAS_MMX 0x00000002 |
39 #define CPU_HAS_3DNOW 0x00000004 | 39 #define CPU_HAS_MMXEXT 0x00000004 |
40 #define CPU_HAS_SSE 0x00000008 | 40 #define CPU_HAS_3DNOW 0x00000010 |
41 #define CPU_HAS_ALTIVEC 0x00000010 | 41 #define CPU_HAS_3DNOWEXT 0x00000020 |
42 #define CPU_HAS_SSE 0x00000040 | |
43 #define CPU_HAS_SSE2 0x00000080 | |
44 #define CPU_HAS_ALTIVEC 0x00000100 | |
42 | 45 |
43 static __inline__ int CPU_haveCPUID() | 46 static __inline__ int CPU_haveCPUID() |
44 { | 47 { |
45 int has_CPUID = 0; | 48 int has_CPUID = 0; |
46 #if defined(__GNUC__) && defined(i386) | 49 #if defined(__GNUC__) && defined(i386) |
47 __asm__ ( | 50 __asm__ ( |
48 "push %%ecx\n" | |
49 " pushfl # Get original EFLAGS \n" | 51 " pushfl # Get original EFLAGS \n" |
50 " popl %%eax \n" | 52 " popl %%eax \n" |
51 " movl %%eax,%%ecx \n" | 53 " movl %%eax,%%ecx \n" |
52 " xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n" | 54 " xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n" |
53 " pushl %%eax # Save new EFLAGS value on stack \n" | 55 " pushl %%eax # Save new EFLAGS value on stack \n" |
56 " popl %%eax # Store new EFLAGS in EAX \n" | 58 " popl %%eax # Store new EFLAGS in EAX \n" |
57 " xorl %%ecx,%%eax # Can not toggle ID bit, \n" | 59 " xorl %%ecx,%%eax # Can not toggle ID bit, \n" |
58 " jz 1f # Processor=80486 \n" | 60 " jz 1f # Processor=80486 \n" |
59 " movl $1,%0 # We have CPUID support \n" | 61 " movl $1,%0 # We have CPUID support \n" |
60 "1: \n" | 62 "1: \n" |
61 "pop %%ecx\n" | |
62 : "=m" (has_CPUID) | 63 : "=m" (has_CPUID) |
63 : | 64 : |
64 : "%eax", "%ecx" | 65 : "%eax", "%ecx" |
65 ); | 66 ); |
66 #elif defined(_MSC_VER) | 67 #elif defined(_MSC_VER) |
85 static __inline__ int CPU_getCPUIDFeatures() | 86 static __inline__ int CPU_getCPUIDFeatures() |
86 { | 87 { |
87 int features = 0; | 88 int features = 0; |
88 #if defined(__GNUC__) && defined(i386) | 89 #if defined(__GNUC__) && defined(i386) |
89 __asm__ ( | 90 __asm__ ( |
90 "push %%ebx\n" | 91 " movl %%ebx,%%edi\n" |
91 "push %%ecx\n" | |
92 "push %%edx\n" | |
93 " xorl %%eax,%%eax # Set up for CPUID instruction \n" | 92 " xorl %%eax,%%eax # Set up for CPUID instruction \n" |
94 " cpuid # Get and save vendor ID \n" | 93 " cpuid # Get and save vendor ID \n" |
95 " cmpl $1,%%eax # Make sure 1 is valid input for CPUID\n" | 94 " cmpl $1,%%eax # Make sure 1 is valid input for CPUID\n" |
96 " jl 1f # We dont have the CPUID instruction\n" | 95 " jl 1f # We dont have the CPUID instruction\n" |
97 " xorl %%eax,%%eax \n" | 96 " xorl %%eax,%%eax \n" |
98 " incl %%eax \n" | 97 " incl %%eax \n" |
99 " cpuid # Get family/model/stepping/features\n" | 98 " cpuid # Get family/model/stepping/features\n" |
100 " movl %%edx,%0 \n" | 99 " movl %%edx,%0 \n" |
101 "1: \n" | 100 "1: \n" |
102 "pop %%edx\n" | 101 " movl %%edi,%%ebx\n" |
103 "pop %%ecx\n" | |
104 "pop %%ebx\n" | |
105 : "=m" (features) | 102 : "=m" (features) |
106 : | 103 : |
107 : "%eax", "%ebx", "%ecx", "%edx" | 104 : "%eax", "%ebx", "%ecx", "%edx", "%edi" |
108 ); | 105 ); |
109 #elif defined(_MSC_VER) | 106 #elif defined(_MSC_VER) |
110 __asm { | 107 __asm { |
111 xor eax, eax ; Set up for CPUID instruction | 108 xor eax, eax ; Set up for CPUID instruction |
112 cpuid ; Get and save vendor ID | 109 cpuid ; Get and save vendor ID |
120 } | 117 } |
121 #endif | 118 #endif |
122 return features; | 119 return features; |
123 } | 120 } |
124 | 121 |
125 static __inline__ int CPU_haveRDTSC() | 122 static __inline__ int CPU_getCPUIDFeaturesExt() |
126 { | 123 { |
127 if ( CPU_haveCPUID() ) { | 124 int features = 0; |
128 return (CPU_getCPUIDFeatures() & 0x00000010); | |
129 } | |
130 return 0; | |
131 } | |
132 | |
133 static __inline__ int CPU_haveMMX() | |
134 { | |
135 if ( CPU_haveCPUID() ) { | |
136 return (CPU_getCPUIDFeatures() & 0x00800000); | |
137 } | |
138 return 0; | |
139 } | |
140 | |
141 static __inline__ int CPU_have3DNow() | |
142 { | |
143 int has_3DNow = 0; | |
144 if ( !CPU_haveCPUID() ) { | |
145 return 0; | |
146 } | |
147 #if defined(__GNUC__) && defined(i386) | 125 #if defined(__GNUC__) && defined(i386) |
148 __asm__ ( | 126 __asm__ ( |
149 "push %%ebx\n" | 127 " movl %%ebx,%%edi\n" |
150 "push %%ecx\n" | |
151 "push %%edx\n" | |
152 " movl $0x80000000,%%eax # Query for extended functions \n" | 128 " movl $0x80000000,%%eax # Query for extended functions \n" |
153 " cpuid # Get extended function limit \n" | 129 " cpuid # Get extended function limit \n" |
154 " cmpl $0x80000001,%%eax \n" | 130 " cmpl $0x80000001,%%eax \n" |
155 " jbe 1f # Nope, we dont have function 800000001h\n" | 131 " jbe 1f # Nope, we dont have function 800000001h\n" |
156 " movl $0x80000001,%%eax # Setup extended function 800000001h\n" | 132 " movl $0x80000001,%%eax # Setup extended function 800000001h\n" |
157 " cpuid # and get the information \n" | 133 " cpuid # and get the information \n" |
158 " testl $0x80000000,%%edx # Bit 31 is set if 3DNow! present \n" | 134 " movl %%edx,%0 \n" |
159 " jz 1f # Nope, we dont have 3DNow support\n" | |
160 " movl $1,%0 # Yep, we have 3DNow! support! \n" | |
161 "1: \n" | 135 "1: \n" |
162 "pop %%edx\n" | 136 " movl %%edi,%%ebx\n" |
163 "pop %%ecx\n" | 137 : "=m" (features) |
164 "pop %%ebx\n" | |
165 : "=m" (has_3DNow) | |
166 : | 138 : |
167 : "%eax", "%ebx", "%ecx", "%edx" | 139 : "%eax", "%ebx", "%ecx", "%edx", "%edi" |
168 ); | 140 ); |
169 #elif defined(_MSC_VER) | 141 #elif defined(_MSC_VER) |
170 __asm { | 142 __asm { |
171 mov eax,80000000h ; Query for extended functions | 143 mov eax,80000000h ; Query for extended functions |
172 cpuid ; Get extended function limit | 144 cpuid ; Get extended function limit |
173 cmp eax,80000001h | 145 cmp eax,80000001h |
174 jbe done ; Nope, we dont have function 800000001h | 146 jbe done ; Nope, we dont have function 800000001h |
175 mov eax,80000001h ; Setup extended function 800000001h | 147 mov eax,80000001h ; Setup extended function 800000001h |
176 cpuid ; and get the information | 148 cpuid ; and get the information |
177 test edx,80000000h ; Bit 31 is set if 3DNow! present | 149 mov features,edx |
178 jz done ; Nope, we dont have 3DNow support | |
179 mov has_3DNow,1 ; Yep, we have 3DNow! support! | |
180 done: | 150 done: |
181 } | 151 } |
182 #endif | 152 #endif |
183 return has_3DNow; | 153 return features; |
154 } | |
155 | |
156 static __inline__ int CPU_haveRDTSC() | |
157 { | |
158 if ( CPU_haveCPUID() ) { | |
159 return (CPU_getCPUIDFeatures() & 0x00000010); | |
160 } | |
161 return 0; | |
162 } | |
163 | |
164 static __inline__ int CPU_haveMMX() | |
165 { | |
166 if ( CPU_haveCPUID() ) { | |
167 return (CPU_getCPUIDFeatures() & 0x00800000); | |
168 } | |
169 return 0; | |
170 } | |
171 | |
172 static __inline__ int CPU_haveMMXExt() | |
173 { | |
174 if ( CPU_haveCPUID() ) { | |
175 return (CPU_getCPUIDFeaturesExt() & 0x00400000); | |
176 } | |
177 return 0; | |
178 } | |
179 | |
180 static __inline__ int CPU_have3DNow() | |
181 { | |
182 if ( CPU_haveCPUID() ) { | |
183 return (CPU_getCPUIDFeaturesExt() & 0x80000000); | |
184 } | |
185 return 0; | |
186 } | |
187 | |
188 static __inline__ int CPU_have3DNowExt() | |
189 { | |
190 if ( CPU_haveCPUID() ) { | |
191 return (CPU_getCPUIDFeaturesExt() & 0x40000000); | |
192 } | |
193 return 0; | |
184 } | 194 } |
185 | 195 |
186 static __inline__ int CPU_haveSSE() | 196 static __inline__ int CPU_haveSSE() |
187 { | 197 { |
188 if ( CPU_haveCPUID() ) { | 198 if ( CPU_haveCPUID() ) { |
189 return (CPU_getCPUIDFeatures() & 0x02000000); | 199 return (CPU_getCPUIDFeatures() & 0x02000000); |
200 } | |
201 return 0; | |
202 } | |
203 | |
204 static __inline__ int CPU_haveSSE2() | |
205 { | |
206 if ( CPU_haveCPUID() ) { | |
207 return (CPU_getCPUIDFeatures() & 0x04000000); | |
190 } | 208 } |
191 return 0; | 209 return 0; |
192 } | 210 } |
193 | 211 |
194 static __inline__ int CPU_haveAltiVec() | 212 static __inline__ int CPU_haveAltiVec() |
227 SDL_CPUFeatures |= CPU_HAS_SSE; | 245 SDL_CPUFeatures |= CPU_HAS_SSE; |
228 } | 246 } |
229 if ( CPU_haveAltiVec() ) { | 247 if ( CPU_haveAltiVec() ) { |
230 SDL_CPUFeatures |= CPU_HAS_ALTIVEC; | 248 SDL_CPUFeatures |= CPU_HAS_ALTIVEC; |
231 } | 249 } |
250 if ( CPU_haveMMXExt() ) { | |
251 SDL_CPUFeatures |= CPU_HAS_MMXEXT; | |
252 } | |
253 if ( CPU_have3DNowExt() ) { | |
254 SDL_CPUFeatures |= CPU_HAS_3DNOWEXT; | |
255 } | |
256 if ( CPU_haveSSE2() ) { | |
257 SDL_CPUFeatures |= CPU_HAS_SSE2; | |
258 } | |
232 } | 259 } |
233 return SDL_CPUFeatures; | 260 return SDL_CPUFeatures; |
234 } | 261 } |
235 | 262 |
236 SDL_bool SDL_HasRDTSC() | 263 SDL_bool SDL_HasRDTSC() |
269 { | 296 { |
270 if ( SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC ) { | 297 if ( SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC ) { |
271 return SDL_TRUE; | 298 return SDL_TRUE; |
272 } | 299 } |
273 return SDL_FALSE; | 300 return SDL_FALSE; |
301 } | |
302 | |
303 SDL_bool SDL_HasMMXExt() | |
304 { | |
305 if ( SDL_GetCPUFeatures() & CPU_HAS_MMXEXT ) { | |
306 return SDL_TRUE; | |
307 } | |
308 return SDL_FALSE; | |
309 } | |
310 | |
311 SDL_bool SDL_Has3DNowExt() | |
312 { | |
313 if ( SDL_GetCPUFeatures() & CPU_HAS_3DNOWEXT ) { | |
314 return SDL_TRUE; | |
315 } | |
316 return SDL_FALSE; | |
317 } | |
318 | |
319 SDL_bool SDL_HasSSE2() | |
320 { | |
321 if ( SDL_GetCPUFeatures() & CPU_HAS_SSE2 ) { | |
322 return SDL_TRUE; | |
323 } | |
324 return SDL_FALSE; | |
274 } | 325 } |
275 | 326 |
276 #ifdef TEST_MAIN | 327 #ifdef TEST_MAIN |
277 | 328 |
278 #include <stdio.h> | 329 #include <stdio.h> |
279 | 330 |
280 int main() | 331 int main() |
281 { | 332 { |
282 printf("RDTSC: %d\n", SDL_HasRDTSC()); | 333 printf("RDTSC: %d\n", SDL_HasRDTSC()); |
283 printf("MMX: %d\n", SDL_HasMMX()); | 334 printf("MMX: %d\n", SDL_HasMMX()); |
335 printf("MMXExt: %d\n", SDL_HasMMXExt()); | |
284 printf("3DNow: %d\n", SDL_Has3DNow()); | 336 printf("3DNow: %d\n", SDL_Has3DNow()); |
337 printf("3DNowExt: %d\n", SDL_Has3DNowExt()); | |
285 printf("SSE: %d\n", SDL_HasSSE()); | 338 printf("SSE: %d\n", SDL_HasSSE()); |
339 printf("SSE2: %d\n", SDL_HasSSE2()); | |
286 printf("AltiVec: %d\n", SDL_HasAltiVec()); | 340 printf("AltiVec: %d\n", SDL_HasAltiVec()); |
287 return 0; | 341 return 0; |
288 } | 342 } |
289 | 343 |
290 #endif /* TEST_MAIN */ | 344 #endif /* TEST_MAIN */ |