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