Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / usr.sbin / cpuctl / arch / i386-asm.S
blobe2ebab3be8263e1558a7494aa46b05e1ee8f5963
1 /*      $NetBSD: cpufunc.S,v 1.9 2008/05/03 06:11:19 yamt Exp $ */
3 /*-
4  * Copyright (c) 1998, 2000, 2004, 2006, 2007 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
29 #include <machine/asm.h>
30 #include <machine/cputypes.h>
31 #include <machine/psl.h>
33         .data
35 _C_LABEL(cpu):
36         .long   0
37         .globl  _C_LABEL(cpu)
38 _C_LABEL(cpu_info_level):
39         .long   -1
40         .globl  _C_LABEL(cpu_info_level)
42         .text
44 ENTRY(x86_cpuid2)
45         pushl   %ebx
46         pushl   %edi
47         movl    12(%esp), %eax
48         movl    16(%esp), %ecx
49         movl    20(%esp), %edi
50         cpuid
51         movl    %eax, 0(%edi)
52         movl    %ebx, 4(%edi)
53         movl    %ecx, 8(%edi)
54         movl    %edx, 12(%edi)
55         popl    %edi
56         popl    %ebx
57         ret
58 END(x86_cpuid2)
60 ENTRY(x86_identify)
61         pushl   %ebx
62         /* Try to toggle alignment check flag; does not exist on 386. */
63         pushfl
64         popl    %eax
65         movl    %eax,%ecx
66         orl     $PSL_AC,%eax
67         pushl   %eax
68         popfl
69         pushfl
70         popl    %eax
71         xorl    %ecx,%eax
72         andl    $PSL_AC,%eax
73         pushl   %ecx
74         popfl
75         testl   %eax,%eax
76         jnz     try486
78         /*
79          * Try the test of a NexGen CPU -- ZF will not change on a DIV
80          * instruction on a NexGen, it will on an i386.  Documented in
81          * Nx586 Processor Recognition Application Note, NexGen, Inc.
82          */
83         movl    $0x5555,%eax
84         xorl    %edx,%edx
85         movl    $2,%ecx
86         divl    %ecx
87         jnz     is386
89 isnx586:
90         /*
91          * Don't try cpuid, as Nx586s reportedly don't support the
92          * PSL_ID bit.
93          */
94         movl    $CPU_NX586,_C_LABEL(cpu)
95         jmp     2f
96 is386:
97         movl    $CPU_386,_C_LABEL(cpu)
98         jmp     2f
100 try486: /* Try to toggle identification flag; does not exist on early 486s. */
101         pushfl
102         popl    %eax
103         movl    %eax,%ecx
104         xorl    $PSL_ID,%eax
105         pushl   %eax
106         popfl
107         pushfl
108         popl    %eax
109         xorl    %ecx,%eax
110         andl    $PSL_ID,%eax
111         pushl   %ecx
112         popfl
114         testl   %eax,%eax
115         jnz     try586
116 is486:  movl    $CPU_486,_C_LABEL(cpu)
117         /*
118          * Check Cyrix CPU
119          * Cyrix CPUs do not change the undefined flags following
120          * execution of the divide instruction which divides 5 by 2.
121          *
122          * Note: CPUID is enabled on M2, so it passes another way.
123          */
124         pushfl
125         movl    $0x5555, %eax
126         xorl    %edx, %edx
127         movl    $2, %ecx
128         clc
129         divl    %ecx
130         jnc     trycyrix486
131         popfl
132         jmp 2f
133 trycyrix486:
134         movl    $CPU_6x86,_C_LABEL(cpu) # set CPU type
135         /*
136          * Check for Cyrix 486 CPU by seeing if the flags change during a
137          * divide. This is documented in the Cx486SLC/e SMM Programmer's
138          * Guide.
139          */
140         xorl    %edx,%edx
141         cmpl    %edx,%edx               # set flags to known state
142         pushfl
143         popl    %ecx                    # store flags in ecx
144         movl    $-1,%eax
145         movl    $4,%ebx
146         divl    %ebx                    # do a long division
147         pushfl
148         popl    %eax
149         xorl    %ecx,%eax               # are the flags different?
150         testl   $0x8d5,%eax             # only check C|PF|AF|Z|N|V
151         jne     2f                      # yes; must be Cyrix 6x86 CPU
152         movl    $CPU_486DLC,_C_LABEL(cpu)# set CPU type
153         jmp     2f
154 try586: /* Use the `cpuid' instruction. */
155         xorl    %eax,%eax
156         cpuid
157         movl    %eax,_C_LABEL(cpu_info_level)
159         popl    %ebx
160         ret