diff options
author | Franklin Wei <git@fwei.tk> | 2017-01-21 15:18:31 -0500 |
---|---|---|
committer | Franklin Wei <git@fwei.tk> | 2017-12-23 21:01:26 -0500 |
commit | a855d6202536ff28e5aae4f22a0f31d8f5b325d0 (patch) | |
tree | 8c75f224dd64ed360505afa8843d016b0d75000b /apps/plugins/sdl/src/cpuinfo/SDL_cpuinfo.c | |
parent | 01c6dcf6c7b9bb1ad2fa0450f99bacc5f3d3e04b (diff) | |
download | rockbox-a855d6202536ff28e5aae4f22a0f31d8f5b325d0.tar.gz rockbox-a855d6202536ff28e5aae4f22a0f31d8f5b325d0.zip |
Port of Duke Nukem 3D
This ports Fabien Sanglard's Chocolate Duke to run on a version of SDL
for Rockbox.
Change-Id: I8f2c4c78af19de10c1633ed7bb7a997b43256dd9
Diffstat (limited to 'apps/plugins/sdl/src/cpuinfo/SDL_cpuinfo.c')
-rw-r--r-- | apps/plugins/sdl/src/cpuinfo/SDL_cpuinfo.c | 499 |
1 files changed, 499 insertions, 0 deletions
diff --git a/apps/plugins/sdl/src/cpuinfo/SDL_cpuinfo.c b/apps/plugins/sdl/src/cpuinfo/SDL_cpuinfo.c new file mode 100644 index 0000000000..0cd083896c --- /dev/null +++ b/apps/plugins/sdl/src/cpuinfo/SDL_cpuinfo.c | |||
@@ -0,0 +1,499 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 Sam Lantinga | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2.1 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General Public | ||
16 | License along with this library; if not, write to the Free Software | ||
17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | */ | ||
22 | #include "SDL_config.h" | ||
23 | |||
24 | /* CPU feature detection for SDL */ | ||
25 | |||
26 | #include "SDL.h" | ||
27 | #include "SDL_cpuinfo.h" | ||
28 | |||
29 | #if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__)) | ||
30 | #include <sys/sysctl.h> /* For AltiVec check */ | ||
31 | #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP | ||
32 | #include <signal.h> | ||
33 | #include <setjmp.h> | ||
34 | #endif | ||
35 | |||
36 | #define CPU_HAS_RDTSC 0x00000001 | ||
37 | #define CPU_HAS_MMX 0x00000002 | ||
38 | #define CPU_HAS_MMXEXT 0x00000004 | ||
39 | #define CPU_HAS_3DNOW 0x00000010 | ||
40 | #define CPU_HAS_3DNOWEXT 0x00000020 | ||
41 | #define CPU_HAS_SSE 0x00000040 | ||
42 | #define CPU_HAS_SSE2 0x00000080 | ||
43 | #define CPU_HAS_ALTIVEC 0x00000100 | ||
44 | |||
45 | #if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__ | ||
46 | /* This is the brute force way of detecting instruction sets... | ||
47 | the idea is borrowed from the libmpeg2 library - thanks! | ||
48 | */ | ||
49 | static jmp_buf jmpbuf; | ||
50 | static void illegal_instruction(int sig) | ||
51 | { | ||
52 | longjmp(jmpbuf, 1); | ||
53 | } | ||
54 | #endif /* HAVE_SETJMP */ | ||
55 | |||
56 | static __inline__ int CPU_haveCPUID(void) | ||
57 | { | ||
58 | int has_CPUID = 0; | ||
59 | #if defined(__GNUC__) && defined(i386) | ||
60 | __asm__ ( | ||
61 | " pushfl # Get original EFLAGS \n" | ||
62 | " popl %%eax \n" | ||
63 | " movl %%eax,%%ecx \n" | ||
64 | " xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n" | ||
65 | " pushl %%eax # Save new EFLAGS value on stack \n" | ||
66 | " popfl # Replace current EFLAGS value \n" | ||
67 | " pushfl # Get new EFLAGS \n" | ||
68 | " popl %%eax # Store new EFLAGS in EAX \n" | ||
69 | " xorl %%ecx,%%eax # Can not toggle ID bit, \n" | ||
70 | " jz 1f # Processor=80486 \n" | ||
71 | " movl $1,%0 # We have CPUID support \n" | ||
72 | "1: \n" | ||
73 | : "=m" (has_CPUID) | ||
74 | : | ||
75 | : "%eax", "%ecx" | ||
76 | ); | ||
77 | #elif defined(__GNUC__) && defined(__x86_64__) | ||
78 | /* Technically, if this is being compiled under __x86_64__ then it has | ||
79 | CPUid by definition. But it's nice to be able to prove it. :) */ | ||
80 | __asm__ ( | ||
81 | " pushfq # Get original EFLAGS \n" | ||
82 | " popq %%rax \n" | ||
83 | " movq %%rax,%%rcx \n" | ||
84 | " xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n" | ||
85 | " pushq %%rax # Save new EFLAGS value on stack \n" | ||
86 | " popfq # Replace current EFLAGS value \n" | ||
87 | " pushfq # Get new EFLAGS \n" | ||
88 | " popq %%rax # Store new EFLAGS in EAX \n" | ||
89 | " xorl %%ecx,%%eax # Can not toggle ID bit, \n" | ||
90 | " jz 1f # Processor=80486 \n" | ||
91 | " movl $1,%0 # We have CPUID support \n" | ||
92 | "1: \n" | ||
93 | : "=m" (has_CPUID) | ||
94 | : | ||
95 | : "%rax", "%rcx" | ||
96 | ); | ||
97 | #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) | ||
98 | __asm { | ||
99 | pushfd ; Get original EFLAGS | ||
100 | pop eax | ||
101 | mov ecx, eax | ||
102 | xor eax, 200000h ; Flip ID bit in EFLAGS | ||
103 | push eax ; Save new EFLAGS value on stack | ||
104 | popfd ; Replace current EFLAGS value | ||
105 | pushfd ; Get new EFLAGS | ||
106 | pop eax ; Store new EFLAGS in EAX | ||
107 | xor eax, ecx ; Can not toggle ID bit, | ||
108 | jz done ; Processor=80486 | ||
109 | mov has_CPUID,1 ; We have CPUID support | ||
110 | done: | ||
111 | } | ||
112 | #elif defined(__sun) && defined(__i386) | ||
113 | __asm ( | ||
114 | " pushfl \n" | ||
115 | " popl %eax \n" | ||
116 | " movl %eax,%ecx \n" | ||
117 | " xorl $0x200000,%eax \n" | ||
118 | " pushl %eax \n" | ||
119 | " popfl \n" | ||
120 | " pushfl \n" | ||
121 | " popl %eax \n" | ||
122 | " xorl %ecx,%eax \n" | ||
123 | " jz 1f \n" | ||
124 | " movl $1,-8(%ebp) \n" | ||
125 | "1: \n" | ||
126 | ); | ||
127 | #elif defined(__sun) && defined(__amd64) | ||
128 | __asm ( | ||
129 | " pushfq \n" | ||
130 | " popq %rax \n" | ||
131 | " movq %rax,%rcx \n" | ||
132 | " xorl $0x200000,%eax \n" | ||
133 | " pushq %rax \n" | ||
134 | " popfq \n" | ||
135 | " pushfq \n" | ||
136 | " popq %rax \n" | ||
137 | " xorl %ecx,%eax \n" | ||
138 | " jz 1f \n" | ||
139 | " movl $1,-8(%rbp) \n" | ||
140 | "1: \n" | ||
141 | ); | ||
142 | #endif | ||
143 | return has_CPUID; | ||
144 | } | ||
145 | |||
146 | static __inline__ int CPU_getCPUIDFeatures(void) | ||
147 | { | ||
148 | int features = 0; | ||
149 | #if defined(__GNUC__) && defined(i386) | ||
150 | __asm__ ( | ||
151 | " xorl %%eax,%%eax # Set up for CPUID instruction \n" | ||
152 | " pushl %%ebx \n" | ||
153 | " cpuid # Get and save vendor ID \n" | ||
154 | " popl %%ebx \n" | ||
155 | " cmpl $1,%%eax # Make sure 1 is valid input for CPUID\n" | ||
156 | " jl 1f # We dont have the CPUID instruction\n" | ||
157 | " xorl %%eax,%%eax \n" | ||
158 | " incl %%eax \n" | ||
159 | " pushl %%ebx \n" | ||
160 | " cpuid # Get family/model/stepping/features\n" | ||
161 | " popl %%ebx \n" | ||
162 | " movl %%edx,%0 \n" | ||
163 | "1: \n" | ||
164 | : "=m" (features) | ||
165 | : | ||
166 | : "%eax", "%ecx", "%edx" | ||
167 | ); | ||
168 | #elif defined(__GNUC__) && defined(__x86_64__) | ||
169 | __asm__ ( | ||
170 | " xorl %%eax,%%eax # Set up for CPUID instruction \n" | ||
171 | " pushq %%rbx \n" | ||
172 | " cpuid # Get and save vendor ID \n" | ||
173 | " popq %%rbx \n" | ||
174 | " cmpl $1,%%eax # Make sure 1 is valid input for CPUID\n" | ||
175 | " jl 1f # We dont have the CPUID instruction\n" | ||
176 | " xorl %%eax,%%eax \n" | ||
177 | " incl %%eax \n" | ||
178 | " pushq %%rbx \n" | ||
179 | " cpuid # Get family/model/stepping/features\n" | ||
180 | " popq %%rbx \n" | ||
181 | " movl %%edx,%0 \n" | ||
182 | "1: \n" | ||
183 | : "=m" (features) | ||
184 | : | ||
185 | : "%rax", "%rcx", "%rdx" | ||
186 | ); | ||
187 | #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) | ||
188 | __asm { | ||
189 | xor eax, eax ; Set up for CPUID instruction | ||
190 | push ebx | ||
191 | cpuid ; Get and save vendor ID | ||
192 | pop ebx | ||
193 | cmp eax, 1 ; Make sure 1 is valid input for CPUID | ||
194 | jl done ; We dont have the CPUID instruction | ||
195 | xor eax, eax | ||
196 | inc eax | ||
197 | push ebx | ||
198 | cpuid ; Get family/model/stepping/features | ||
199 | pop ebx | ||
200 | mov features, edx | ||
201 | done: | ||
202 | } | ||
203 | #elif defined(__sun) && (defined(__i386) || defined(__amd64)) | ||
204 | __asm( | ||
205 | " xorl %eax,%eax \n" | ||
206 | " pushl %ebx \n" | ||
207 | " cpuid \n" | ||
208 | " popl %ebx \n" | ||
209 | " cmpl $1,%eax \n" | ||
210 | " jl 1f \n" | ||
211 | " xorl %eax,%eax \n" | ||
212 | " incl %eax \n" | ||
213 | " pushl %ebx \n" | ||
214 | " cpuid \n" | ||
215 | " popl %ebx \n" | ||
216 | #ifdef __i386 | ||
217 | " movl %edx,-8(%ebp) \n" | ||
218 | #else | ||
219 | " movl %edx,-8(%rbp) \n" | ||
220 | #endif | ||
221 | "1: \n" | ||
222 | #endif | ||
223 | return features; | ||
224 | } | ||
225 | |||
226 | static __inline__ int CPU_getCPUIDFeaturesExt(void) | ||
227 | { | ||
228 | int features = 0; | ||
229 | #if defined(__GNUC__) && defined(i386) | ||
230 | __asm__ ( | ||
231 | " movl $0x80000000,%%eax # Query for extended functions \n" | ||
232 | " pushl %%ebx \n" | ||
233 | " cpuid # Get extended function limit \n" | ||
234 | " popl %%ebx \n" | ||
235 | " cmpl $0x80000001,%%eax \n" | ||
236 | " jl 1f # Nope, we dont have function 800000001h\n" | ||
237 | " movl $0x80000001,%%eax # Setup extended function 800000001h\n" | ||
238 | " pushl %%ebx \n" | ||
239 | " cpuid # and get the information \n" | ||
240 | " popl %%ebx \n" | ||
241 | " movl %%edx,%0 \n" | ||
242 | "1: \n" | ||
243 | : "=m" (features) | ||
244 | : | ||
245 | : "%eax", "%ecx", "%edx" | ||
246 | ); | ||
247 | #elif defined(__GNUC__) && defined (__x86_64__) | ||
248 | __asm__ ( | ||
249 | " movl $0x80000000,%%eax # Query for extended functions \n" | ||
250 | " pushq %%rbx \n" | ||
251 | " cpuid # Get extended function limit \n" | ||
252 | " popq %%rbx \n" | ||
253 | " cmpl $0x80000001,%%eax \n" | ||
254 | " jl 1f # Nope, we dont have function 800000001h\n" | ||
255 | " movl $0x80000001,%%eax # Setup extended function 800000001h\n" | ||
256 | " pushq %%rbx \n" | ||
257 | " cpuid # and get the information \n" | ||
258 | " popq %%rbx \n" | ||
259 | " movl %%edx,%0 \n" | ||
260 | "1: \n" | ||
261 | : "=m" (features) | ||
262 | : | ||
263 | : "%rax", "%rcx", "%rdx" | ||
264 | ); | ||
265 | #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) | ||
266 | __asm { | ||
267 | mov eax,80000000h ; Query for extended functions | ||
268 | push ebx | ||
269 | cpuid ; Get extended function limit | ||
270 | pop ebx | ||
271 | cmp eax,80000001h | ||
272 | jl done ; Nope, we dont have function 800000001h | ||
273 | mov eax,80000001h ; Setup extended function 800000001h | ||
274 | push ebx | ||
275 | cpuid ; and get the information | ||
276 | pop ebx | ||
277 | mov features,edx | ||
278 | done: | ||
279 | } | ||
280 | #elif defined(__sun) && ( defined(__i386) || defined(__amd64) ) | ||
281 | __asm ( | ||
282 | " movl $0x80000000,%eax \n" | ||
283 | " pushl %ebx \n" | ||
284 | " cpuid \n" | ||
285 | " popl %ebx \n" | ||
286 | " cmpl $0x80000001,%eax \n" | ||
287 | " jl 1f \n" | ||
288 | " movl $0x80000001,%eax \n" | ||
289 | " pushl %ebx \n" | ||
290 | " cpuid \n" | ||
291 | " popl %ebx \n" | ||
292 | #ifdef __i386 | ||
293 | " movl %edx,-8(%ebp) \n" | ||
294 | #else | ||
295 | " movl %edx,-8(%rbp) \n" | ||
296 | #endif | ||
297 | "1: \n" | ||
298 | ); | ||
299 | #endif | ||
300 | return features; | ||
301 | } | ||
302 | |||
303 | static __inline__ int CPU_haveRDTSC(void) | ||
304 | { | ||
305 | if ( CPU_haveCPUID() ) { | ||
306 | return (CPU_getCPUIDFeatures() & 0x00000010); | ||
307 | } | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | static __inline__ int CPU_haveMMX(void) | ||
312 | { | ||
313 | if ( CPU_haveCPUID() ) { | ||
314 | return (CPU_getCPUIDFeatures() & 0x00800000); | ||
315 | } | ||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | static __inline__ int CPU_haveMMXExt(void) | ||
320 | { | ||
321 | if ( CPU_haveCPUID() ) { | ||
322 | return (CPU_getCPUIDFeaturesExt() & 0x00400000); | ||
323 | } | ||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | static __inline__ int CPU_have3DNow(void) | ||
328 | { | ||
329 | if ( CPU_haveCPUID() ) { | ||
330 | return (CPU_getCPUIDFeaturesExt() & 0x80000000); | ||
331 | } | ||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | static __inline__ int CPU_have3DNowExt(void) | ||
336 | { | ||
337 | if ( CPU_haveCPUID() ) { | ||
338 | return (CPU_getCPUIDFeaturesExt() & 0x40000000); | ||
339 | } | ||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | static __inline__ int CPU_haveSSE(void) | ||
344 | { | ||
345 | if ( CPU_haveCPUID() ) { | ||
346 | return (CPU_getCPUIDFeatures() & 0x02000000); | ||
347 | } | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | static __inline__ int CPU_haveSSE2(void) | ||
352 | { | ||
353 | if ( CPU_haveCPUID() ) { | ||
354 | return (CPU_getCPUIDFeatures() & 0x04000000); | ||
355 | } | ||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | static __inline__ int CPU_haveAltiVec(void) | ||
360 | { | ||
361 | volatile int altivec = 0; | ||
362 | #if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__)) | ||
363 | int selectors[2] = { CTL_HW, HW_VECTORUNIT }; | ||
364 | int hasVectorUnit = 0; | ||
365 | size_t length = sizeof(hasVectorUnit); | ||
366 | int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0); | ||
367 | if( 0 == error ) | ||
368 | altivec = (hasVectorUnit != 0); | ||
369 | #elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP | ||
370 | void (*handler)(int sig); | ||
371 | handler = signal(SIGILL, illegal_instruction); | ||
372 | if ( setjmp(jmpbuf) == 0 ) { | ||
373 | asm volatile ("mtspr 256, %0\n\t" | ||
374 | "vand %%v0, %%v0, %%v0" | ||
375 | : | ||
376 | : "r" (-1)); | ||
377 | altivec = 1; | ||
378 | } | ||
379 | signal(SIGILL, handler); | ||
380 | #endif | ||
381 | return altivec; | ||
382 | } | ||
383 | |||
384 | static Uint32 SDL_CPUFeatures = 0xFFFFFFFF; | ||
385 | |||
386 | static Uint32 SDL_GetCPUFeatures(void) | ||
387 | { | ||
388 | if ( SDL_CPUFeatures == 0xFFFFFFFF ) { | ||
389 | SDL_CPUFeatures = 0; | ||
390 | if ( CPU_haveRDTSC() ) { | ||
391 | SDL_CPUFeatures |= CPU_HAS_RDTSC; | ||
392 | } | ||
393 | if ( CPU_haveMMX() ) { | ||
394 | SDL_CPUFeatures |= CPU_HAS_MMX; | ||
395 | } | ||
396 | if ( CPU_haveMMXExt() ) { | ||
397 | SDL_CPUFeatures |= CPU_HAS_MMXEXT; | ||
398 | } | ||
399 | if ( CPU_have3DNow() ) { | ||
400 | SDL_CPUFeatures |= CPU_HAS_3DNOW; | ||
401 | } | ||
402 | if ( CPU_have3DNowExt() ) { | ||
403 | SDL_CPUFeatures |= CPU_HAS_3DNOWEXT; | ||
404 | } | ||
405 | if ( CPU_haveSSE() ) { | ||
406 | SDL_CPUFeatures |= CPU_HAS_SSE; | ||
407 | } | ||
408 | if ( CPU_haveSSE2() ) { | ||
409 | SDL_CPUFeatures |= CPU_HAS_SSE2; | ||
410 | } | ||
411 | if ( CPU_haveAltiVec() ) { | ||
412 | SDL_CPUFeatures |= CPU_HAS_ALTIVEC; | ||
413 | } | ||
414 | } | ||
415 | return SDL_CPUFeatures; | ||
416 | } | ||
417 | |||
418 | SDL_bool SDL_HasRDTSC(void) | ||
419 | { | ||
420 | if ( SDL_GetCPUFeatures() & CPU_HAS_RDTSC ) { | ||
421 | return SDL_TRUE; | ||
422 | } | ||
423 | return SDL_FALSE; | ||
424 | } | ||
425 | |||
426 | SDL_bool SDL_HasMMX(void) | ||
427 | { | ||
428 | if ( SDL_GetCPUFeatures() & CPU_HAS_MMX ) { | ||
429 | return SDL_TRUE; | ||
430 | } | ||
431 | return SDL_FALSE; | ||
432 | } | ||
433 | |||
434 | SDL_bool SDL_HasMMXExt(void) | ||
435 | { | ||
436 | if ( SDL_GetCPUFeatures() & CPU_HAS_MMXEXT ) { | ||
437 | return SDL_TRUE; | ||
438 | } | ||
439 | return SDL_FALSE; | ||
440 | } | ||
441 | |||
442 | SDL_bool SDL_Has3DNow(void) | ||
443 | { | ||
444 | if ( SDL_GetCPUFeatures() & CPU_HAS_3DNOW ) { | ||
445 | return SDL_TRUE; | ||
446 | } | ||
447 | return SDL_FALSE; | ||
448 | } | ||
449 | |||
450 | SDL_bool SDL_Has3DNowExt(void) | ||
451 | { | ||
452 | if ( SDL_GetCPUFeatures() & CPU_HAS_3DNOWEXT ) { | ||
453 | return SDL_TRUE; | ||
454 | } | ||
455 | return SDL_FALSE; | ||
456 | } | ||
457 | |||
458 | SDL_bool SDL_HasSSE(void) | ||
459 | { | ||
460 | if ( SDL_GetCPUFeatures() & CPU_HAS_SSE ) { | ||
461 | return SDL_TRUE; | ||
462 | } | ||
463 | return SDL_FALSE; | ||
464 | } | ||
465 | |||
466 | SDL_bool SDL_HasSSE2(void) | ||
467 | { | ||
468 | if ( SDL_GetCPUFeatures() & CPU_HAS_SSE2 ) { | ||
469 | return SDL_TRUE; | ||
470 | } | ||
471 | return SDL_FALSE; | ||
472 | } | ||
473 | |||
474 | SDL_bool SDL_HasAltiVec(void) | ||
475 | { | ||
476 | if ( SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC ) { | ||
477 | return SDL_TRUE; | ||
478 | } | ||
479 | return SDL_FALSE; | ||
480 | } | ||
481 | |||
482 | #ifdef TEST_MAIN | ||
483 | |||
484 | #include <stdio.h> | ||
485 | |||
486 | int main() | ||
487 | { | ||
488 | printf("RDTSC: %d\n", SDL_HasRDTSC()); | ||
489 | printf("MMX: %d\n", SDL_HasMMX()); | ||
490 | printf("MMXExt: %d\n", SDL_HasMMXExt()); | ||
491 | printf("3DNow: %d\n", SDL_Has3DNow()); | ||
492 | printf("3DNowExt: %d\n", SDL_Has3DNowExt()); | ||
493 | printf("SSE: %d\n", SDL_HasSSE()); | ||
494 | printf("SSE2: %d\n", SDL_HasSSE2()); | ||
495 | printf("AltiVec: %d\n", SDL_HasAltiVec()); | ||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | #endif /* TEST_MAIN */ | ||