OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libcpu/] [i386/] [cpuModel.S] - Blame information for rev 228

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*  cpuModel.S
2
 *
3
 *  This file contains all assembly code for the Intel Cpu identification.
4
 *  It is based on linux cpu detection code.
5
 *
6
 *  Intel also provides public similar code in the book
7
 *  called :
8
 *
9
 *      Pentium Processor Family
10
 *              Developer Family
11
 *      Volume  3 :     Architecture and Programming Manual
12
 *
13
 * At the following place :
14
 *
15
 *      Chapter 5 :     Feature determination
16
 *      Chapter 25:     CPUID instruction
17
 *
18
 *  COPYRIGHT (c) 1998 valette@crf.canon.fr
19
 *
20
 *  The license and distribution terms for this file may be
21
 *  found in the file LICENSE in this distribution or at
22
 *  http://www.OARcorp.com/rtems/license.html.
23
 *
24
 *  $Id: cpuModel.S,v 1.2 2001-09-27 12:01:22 chris Exp $
25
 */
26
 
27
#include 
28
#include 
29
 
30
BEGIN_CODE
31
        PUBLIC(checkCPUtypeSetCr0);
32
/*
33
 * check Processor type: 386, 486, 6x86(L) or CPUID capable processor
34
 */
35
 
36
SYM (checkCPUtypeSetCr0):
37
        /*
38
         *  Assume 386 for now
39
         */
40
        movl $3, SYM (x86)
41
        /*
42
         * Start using the EFLAGS AC bit determination method described in
43
         * the book mentioned above page 5.1. If this bit can be set we
44
         * have a 486 or above.
45
         */
46
        pushfl                          /* save EFLAGS                  */
47
 
48
        pushfl                          /* Get EFLAGS in EAX            */
49
        popl eax
50
 
51
        movl eax,ecx                    /* save original EFLAGS in ECX  */
52
        xorl $EFLAGS_ALIGN_CHECK,eax    /* flip AC bit in EAX           */
53
        pushl eax                       /* set EAX as EFLAGS            */
54
        popfl
55
        pushfl                          /* Get new EFLAGS in EAX        */
56
        popl eax
57
 
58
        xorl ecx,eax                    /* check if AC bit changed      */
59
        andl $EFLAGS_ALIGN_CHECK,eax
60
        je is386                        /* If not : we have a 386       */
61
        /*
62
         *  Assume 486 for now
63
         */
64
        movl $4,SYM (x86)
65
        movl ecx,eax                    /* Restore orig EFLAGS in EAX   */
66
        xorl $EFLAGS_ID,eax             /* flip  ID flag                */
67
        pushl eax                       /* set EAX as EFLAGS            */
68
        popfl
69
        pushfl                          /* Get new EFLAGS in EAX        */
70
        popl eax
71
 
72
        xorl ecx,eax                    /* check if ID bit changed      */
73
        andl $EFLAGS_ID,eax
74
 
75
        /*
76
         * if we are on a straight 486DX,
77
         * SX, or 487SX we can't change it
78
         * OTOH 6x86MXs and MIIs check OK
79
         * Also if we are on a Cyrix 6x86(L)
80
         */
81
        je is486x
82
 
83
isnew:
84
        /*
85
         * restore original EFLAGS
86
         */
87
        popfl
88
        incl SYM(have_cpuid)    /* we have CPUID instruction */
89
 
90
        /* use it to get :
91
         *      processor type,
92
         *      processor model,
93
         *      processor mask,
94
         * by using it with EAX = 1
95
         */
96
        movl $1, eax
97
        cpuid
98
 
99
        movb al, cl             /* save reg for future use */
100
 
101
        andb $0x0f,ah           /* mask processor family   */
102
        movb ah,SYM (x86)       /* put result in x86 var   */
103
 
104
        andb $0xf0, al          /* get model               */
105
        shrb $4, al
106
        movb al,SYM (x86_model) /* store it in x86_model   */
107
 
108
        andb $0x0f, cl          /* get mask revision       */
109
        movb cl,SYM (x86_mask)  /* store it in x86_mask    */
110
 
111
        movl edx,SYM(x86_capability)    /* store feature flags in x86_capability */
112
 
113
        /* get vendor info by using CPUID with EXA = 0 */
114
        xorl eax, eax
115
        cpuid
116
 
117
        /*
118
         * store results contained in ebx, edx, ecx in
119
         * x86_vendor_id variable.
120
         */
121
        movl ebx,SYM(x86_vendor_id)
122
        movl edx,SYM(x86_vendor_id)+4
123
        movl ecx,SYM(x86_vendor_id)+8
124
 
125
        movl cr0,eax            /* 486+ */
126
        andl $(CR0_PAGING | CR0_PROTECTION_ENABLE | CR0_EXTENSION_TYPE), eax
127
        orl $(CR0_ALIGMENT_MASK | CR0_WRITE_PROTECT | CR0_NUMERIC_ERROR | CR0_MONITOR_COPROC),eax
128
        jmp 2f
129
 
130
/* Now we test if we have a Cyrix 6x86(L). We didn't test before to avoid
131
 * clobbering the new BX chipset used with the Pentium II, which has a register
132
 * at the same addresses as those used to access the Cyrix special configuration
133
 * registers (CCRs).
134
 */
135
        /*
136
         * A Cyrix/IBM 6x86(L) preserves flags after dividing 5 by 2
137
         * (and it _must_ be 5 divided by 2) while other CPUs change
138
         * them in undefined ways. We need to know this since we may
139
         * need to enable the CPUID instruction at least.
140
         * We couldn't use this test before since the PPro and PII behave
141
         * like Cyrix chips in this respect.
142
         */
143
is486x: xor ax,ax
144
        sahf
145
        movb $5,al
146
        movb $2,bl
147
        div bl
148
        lahf
149
        cmpb $2,ah
150
        jne ncyrix
151
        /*
152
         * N.B. The pattern of accesses to 0x22 and 0x23 is *essential*
153
         *      so do not try to "optimize" it! For the same reason we
154
         *      do all this with interrupts off.
155
         */
156
#define setCx86(reg, val) \
157
        movb reg,al;    \
158
        outb al,$0x22;  \
159
        movb val,al;    \
160
        outb al,$0x23
161
 
162
#define getCx86(reg) \
163
        movb reg,al;    \
164
        outb al,$0x22;  \
165
        inb $0x23,al
166
 
167
        cli
168
        getCx86($0xc3)          /*  get CCR3 */
169
        movb al,cl              /* Save old value */
170
        movb al,bl
171
        andb $0x0f,bl           /* Enable access to all config registers */
172
        orb $0x10,bl            /* by setting bit 4 */
173
        setCx86($0xc3,bl)
174
 
175
        getCx86($0xe8)          /* now we can get CCR4 */
176
        orb $0x80,al            /* and set bit 7 (CPUIDEN) */
177
        movb al,bl              /* to enable CPUID execution */
178
        setCx86($0xe8,bl)
179
 
180
        getCx86($0xfe)          /* DIR0 : let's check this is a 6x86(L) */
181
        andb $0xf0,al           /* should be 3xh */
182
        cmpb $0x30,al
183
        jne n6x86
184
        getCx86($0xe9)          /* CCR5 : we reset the SLOP bit */
185
        andb $0xfd,al           /* so that udelay calculation */
186
        movb al,bl              /* is correct on 6x86(L) CPUs */
187
        setCx86($0xe9,bl)
188
        setCx86($0xc3,cl)       /* Restore old CCR3 */
189
        sti
190
        jmp isnew               /* We enabled CPUID now */
191
 
192
n6x86:  setCx86($0xc3,cl)       /* Restore old CCR3 */
193
        sti
194
ncyrix:                         /* restore original EFLAGS */
195
        popfl
196
        movl cr0,eax            /* 486 */
197
        andl $(CR0_PAGING | CR0_EXTENSION_TYPE | CR0_PROTECTION_ENABLE),eax     /* Save PG,PE,ET */
198
        orl $(CR0_ALIGMENT_MASK | CR0_WRITE_PROTECT | CR0_NUMERIC_ERROR | CR0_MONITOR_COPROC),eax       /* set AM, WP, NE and MP */
199
        jmp 2f
200
is386:                          /* restore original EFLAGS */
201
        popfl
202
        movl cr0,eax            /* 386 */
203
        andl $(CR0_PAGING | CR0_EXTENSION_TYPE | CR0_PROTECTION_ENABLE),eax     /* Save PG,PE,ET */
204
        orl $CR0_MONITOR_COPROC,eax             /* set MP */
205
2:      movl eax,cr0
206
        call check_x87
207
        ret
208
 
209
 
210
/*
211
 * We depend on ET to be correct. This checks for 287/387.
212
 */
213
check_x87:
214
        movb $0,SYM(hard_math)
215
        clts
216
        fninit
217
        fstsw ax
218
        cmpb $0,al
219
        je 1f
220
        movl cr0,eax            /* no coprocessor: have to set bits */
221
        xorl $4,eax             /* set EM */
222
        movl eax,cr0
223
        ret
224
        .align 16
225
1:      movb $1,SYM(hard_math)
226
        .byte 0xDB,0xE4         /* fsetpm for 287, ignored by 387 */
227
        ret
228
 
229
END_CODE
230
 
231
BEGIN_DATA
232
        PUBLIC(x86)
233
        PUBLIC(have_cpuid)
234
        PUBLIC(x86_model)
235
        PUBLIC(x86_mask)
236
        PUBLIC(x86_capability)
237
        PUBLIC(x86_vendor_id)
238
        PUBLIC(hard_math)
239
 
240
SYM(x86):
241
        .byte 0
242
SYM(have_cpuid):
243
        .long 0
244
SYM(x86_model):
245
        .byte 0
246
SYM(x86_mask):
247
        .byte 0
248
SYM(x86_capability):
249
        .long 0
250
SYM(x86_vendor_id):
251
        .zero 13
252
SYM(hard_math):
253
        .byte 0
254
END_DATA
255
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.