Rev 1905 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1905 | serge | 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 | |||
3960 | Serge | 91 | NONEXEC_STACK |