Updated PCI IDs to latest snapshot.
[tangerine.git] / arch / i386-pc / exec / getcpu.s
blobff34755ec480260541deea0d2dc2758e9d11143d
1 #/*
2 # Copyright © 2000, The AROS Development Team. All rights reserved.
3 # $Id$
5 # Desc: CPU detection routine
6 # Lang: english
7 #*/
9 .text
11 .globl cpu_params
12 .globl x86
13 .globl x86_vendor
14 .globl x86_model
15 .globl x86_mask
16 .globl x86_hard_math
17 .globl x86_cpuid
18 .globl x86_capability
19 .globl x86_vendor_id
21 .set cpu_params, 0x00000020
22 .set x86, (cpu_params)
23 .set x86_vendor, (cpu_params + 1)
24 .set x86_model, (cpu_params + 2)
25 .set x86_mask, (cpu_params + 3)
26 .set x86_hard_math, (cpu_params + 6)
27 .set x86_cpuid, (cpu_params + 8)
28 .set x86_capability, (cpu_params + 12)
29 .set x86_vendor_id, (cpu_params + 16)
31 .globl exec_GetCPU
32 .type exec_GetCPU,@function
34 exec_GetCPU: pushal
35 movl $-1,x86_cpuid /* No cpuid allowed as far */
37 #/*
38 ## Check whether it is i386 or i486. In i486 we chan change AC bit in EFLAGS
39 ## register. We will use it.
40 #*/
42 movl $3,x86 /* We have at leas i386 if this code works */
43 pushfl /* Get eflags */
44 popl %eax
45 movl %eax,%ecx
46 xorl $0x40000,%eax /* Set AC flag. If it's possible, then we have 486 */
47 pushl %eax /* Copy %eax to eflags and back to %eax */
48 popfl
49 pushfl
50 popl %eax
51 xorl %ecx,%eax /* Mas everything but AC bit (if set) */
52 andl $0x40000,%eax
53 je exec_is386 /* Nope, AC was 0 - i386 only */
55 /* At this point it is sure that we have something better than i386. Assume for
56 ## a while that it is i486. Check whether we can use cpuid instruction. If no,
57 ## then we have i486. If cpuid may be used then get CPU type from this opcode.
58 ## It can be i486 (last few models had cpuid implemented) or better */
60 movl $4,x86 /* Update information */
61 movl %ecx,%eax /* we will try to change ID flag */
62 xorl $0x200000,%eax /* if it is possible then cpuid */
63 pushl %eax /* is implemented */
64 popfl
65 pushfl
66 popl %eax
67 xorl %ecx,%eax
68 pushl %ecx /* Restore eflags register */
69 popfl
70 andl $0x200000,%eax
71 je exec_is486 /* Well, no cpuid. So we can leave now */
73 xorl %eax,%eax /* CPUID! */
74 cpuid
75 movl %eax,x86_cpuid /* The highest cpuid %eax value */
76 movl %ebx,x86_vendor_id /* Processor's vendor ID */
77 movl %ecx,x86_vendor_id+4
78 movl %edx,x86_vendor_id+8
80 orl %eax,%eax /* Can we use more than that above? */
81 je exec_is486 /* Nope, it was i486 */
83 movl $1,%eax /* Get CPU informations (model, stepping etc) */
84 cpuid
85 movb %al,%cl
86 andb $0x0f,%ah
87 movb %ah,x86 /* Model: 5 for 586, 6 for 686 and so on */
88 andb $0xf0,%al
89 shrb $4,%al
90 movb %al,x86_model
91 andb $0x0f,%cl
92 movb %cl,x86_mask
93 movl %edx,x86_capability /* Capabilities like MMX, SSE and more */
95 cmpb $4,x86 /* Updata AttnFlags in ExecBase */
96 jbe exec_is486
97 cmpb $5,x86
98 jbe exec_is486
100 exec_is486: movl %cr0,%eax /* Update CR0 register */
101 andl $0x80000011,%eax /* Save PG,PE,ET */
102 orl $0x00050022,%eax /* Set AM,WP,NE and MP */
103 jmp 2f
105 exec_is386: pushl %ecx
106 popfl
107 movl %cr0,%eax /* Update CR0 reg. i386 version */
108 andl $0x80000011,%eax /* Save PG,PE,ET */
109 orl $2,%eax /* Set MP */
110 2: movl %eax,%cr0
111 call exec_GetFPU /* Detect whether we have FPU */
112 xorl %eax,%eax
113 lldt %ax /* Invalidate LDT */
114 cld /* Clear D flag as needed by AROS and gcc */
115 popal
119 ## Check, whether FPU is present. As we don't need to distinguish FPU type,
120 ## we will just see if it is present.
123 .type exec_GetFPU,@function
124 exec_GetFPU: movb $0,x86_hard_math
125 clts
126 fninit
127 fstsw %ax
128 cmpb $0,%al
129 je 1f
130 movl %cr0,%eax
131 xorl $4,%eax
132 movl %eax,%cr0
134 1: movb $1,x86_hard_math
135 .byte 0xdb,0xe4