562
|
1 /*
|
|
2 getcpucpuflags: get cpuflags for ia32
|
|
3
|
|
4 copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
|
|
5 see COPYING and AUTHORS files in distribution or http:#mpg123.org
|
|
6 initially written by KIMURA Takuhiro (for 3DNow!)
|
|
7 extended for general use by Thomas Orgis
|
|
8
|
|
9 extern int getcpuid(struct cpuflags*)
|
|
10 or just
|
|
11 extern int getcpuid(unsigned int*)
|
|
12 where there is memory for 4 ints
|
|
13 -> the first set of idflags (basic cpu family info)
|
|
14 and the idflags, stdflags, std2flags, extflags written to the parameter
|
|
15 -> 0x00000000 (CPUID instruction not supported)
|
|
16 */
|
|
17
|
|
18 #include "mangle.h"
|
|
19
|
|
20 .text
|
|
21 ALIGN4
|
|
22
|
|
23 .globl ASM_NAME(getcpuflags)
|
|
24 /* .type ASM_NAME(getcpuflags),@function */
|
|
25 ASM_NAME(getcpuflags):
|
|
26 pushl %ebp
|
|
27 movl %esp,%ebp
|
|
28 pushl %edx
|
|
29 pushl %ecx
|
|
30 pushl %ebx
|
|
31 pushl %esi
|
|
32 /* get the int pointer for storing the flags */
|
|
33 movl 8(%ebp), %esi
|
|
34 /* does that one make sense? */
|
|
35 movl $0x80000000,%eax
|
|
36 /* now save the flags and do a check for cpuid availability */
|
|
37 pushfl
|
|
38 pushfl
|
|
39 popl %eax
|
|
40 movl %eax,%ebx
|
|
41 /* set that bit... */
|
|
42 xorl $0x00200000,%eax
|
|
43 pushl %eax
|
|
44 popfl
|
|
45 /* ...and read back the flags to see if it is understood */
|
|
46 pushfl
|
|
47 popl %eax
|
|
48 popfl
|
|
49 cmpl %ebx,%eax
|
|
50 je .Lnocpuid
|
|
51 /* In principle, I would have to check the CPU's identify first to be sure how to interpret the extended flags. */
|
|
52 /* now get the info, first extended */
|
|
53 movl $0x0, 12(%esi) /* clear value */
|
|
54 /* only if supported... */
|
|
55 movl $0x80000000, %eax
|
|
56 cpuid
|
|
57 /* IDT CPUs should not change EAX, generally I hope that non-3DNow cpus do not set a bogus support level here. */
|
|
58 cmpl $0x80000001, %eax
|
|
59 jb .Lnoextended /* Skip ext check without minimal support level. */
|
|
60 /* is supported, get flags value */
|
|
61 movl $0x80000001,%eax
|
|
62 cpuid
|
|
63 movl %edx,12(%esi)
|
|
64 .Lnoextended:
|
|
65 /* then the other ones, called last to get the id flags in %eax for ret */
|
|
66 movl $0x00000001,%eax
|
|
67 cpuid
|
|
68 movl %eax, (%esi)
|
|
69 movl %ecx, 4(%esi)
|
|
70 movl %edx, 8(%esi)
|
|
71 jmp .Lend
|
|
72 ALIGN4
|
|
73 .Lnocpuid:
|
|
74 /* error: set everything to zero */
|
|
75 movl $0, %eax
|
|
76 movl $0, (%esi)
|
|
77 movl $0, 4(%esi)
|
|
78 movl $0, 8(%esi)
|
|
79 movl $0, 12(%esi)
|
|
80 ALIGN4
|
|
81 .Lend:
|
|
82 /* return value are the id flags, still stored in %eax */
|
|
83 popl %esi
|
|
84 popl %ebx
|
|
85 popl %ecx
|
|
86 popl %edx
|
|
87 movl %ebp,%esp
|
|
88 popl %ebp
|
|
89 ret
|
|
90
|
|
91 /* Mark non-executable stack. */
|
|
92 #if defined(__linux__) && defined(__ELF__)
|
|
93 .section .note.GNU-stack,"",%progbits
|
|
94 #endif
|