2
** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY
3
** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT
4
** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX
5
** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE
6
** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com).
7
** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
8
** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A
9
** FULL TEXT OF THE NON-WARRANTY PROVISIONS.
11
** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO
12
** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN
13
** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013,
14
** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR
15
** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF
18
** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED
22
/* $Header: /cvsroot/glide/glide3x/h3/glide3/src/cpudtect.S,v 1.1.1.1 1999/11/24 21:44:53 joseph Exp $ */
23
/* $Log: cpudtect.S,v $
24
* Revision 1.1.1.1 1999/11/24 21:44:53 joseph
25
* Initial checkin for SourceForge
28
/* 4 4/06/99 3:54p Dow */
31
/* 9 3/10/99 10:40a Peter */
32
/* detect katmai-ness */
34
/* 8 1/20/99 5:50p Peter */
35
/* norbert's code for k6 and k7 (?) wc */
37
/* 7 12/09/98 1:11p Peter */
38
/* cpu detection from Norbert for teh rest of the 3DNow!(tm) partners */
40
/* 6 10/03/98 3:35p Peter */
41
/* First pass at dynamic detection of 3DNow!(tm) */
43
/* 5 7/24/98 1:40p Hohn */
45
/* 4 5/28/97 8:23a Peter */
46
/* Merge w/ original glide source */
48
/* 2 3/04/97 9:10p Dow */
49
/* Neutered mutiplatform multiheaded monster. */
56
/* Data for data segment goes here */
57
/* _DATA SEGMENT DWORD USE32 PUBLIC 'DATA' */
60
/* Some useful constants */
62
#define CPUTypeUnknown $0x0ffffffff
63
#define CPUTypePrePent $0x4
64
#define CPUTypeP5 $0x5
65
#define CPUTypeP6 $0x6
67
/* References to external data: */
72
/* _cpu_detect_asm - detect the type of CPU */
76
/* int __cdecl _cpu_detect_asm(void) */
78
/* returns 4 for non-pen */
80
.globl _cpu_detect_asm
81
.type _cpu_detect_asm,@function
83
.L_cpu_detect_asm_P6Stuff:
84
push %esi /* save registers that are not volatile */
89
/* First, determine whether CPUID instruction is available. */
90
/* If it's not, then it's a 386 or 486. */
91
pushf /* push original EFLAGS. */
92
pop %eax /* pop into eax */
93
mov %eax , %ecx /* save original EFLAGS in ecx */
94
xor $0x0200000 , %eax /* flip ID bit in EFLAGS */
95
push %eax /* put it back on stack */
96
popf /* pop into EFLAGS */
97
pushf /* get EFLAGS back */
98
pop %eax /* into eax */
99
xor %ecx , %eax /* check to see if we could toggle ID */
100
jz .L_cpu_detect_asm_NotPentium /* Sorry, not P5 or P6. */
103
/* Now determine whether it's an intel P6 CPU. */
105
/* Is it an Intel CPU? */
106
xor %eax , %eax /* eax = 0. */
107
cpuid /* get cpuid */
108
xor $0x0756e6547 , %ebx /* "Genu" */
109
jnz .L_cpu_detect_asm_NotIntel
110
xor $0x049656e69 , %edx /* "ineI" */
111
jnz .L_cpu_detect_asm_NotIntel
112
xor $0x06c65746e , %ecx /* "ntel" */
113
jnz .L_cpu_detect_asm_NotIntel
115
/* Verifying architecture family */
116
/* eax - type[13:12] family[11:8] model[7:4] revision[3:0] */
117
/* edx - feature bits */
119
cpuid /* get family/model/stepping */
121
shr $8 , %eax /* rid of model & stepping number */
122
and $0x0f , %eax /* use only family */
124
jl .L_cpu_detect_asm_IsP5 /* It's a P5 */
127
/* Intel P6 processor. */
128
/* feature bits are in edx from the cpuid[1] */
129
.L_cpu_detect_asm_IsP6:
130
/* Make sure it supports Memory Type Range Request registers (bit 12) */
134
/* Hmmmm... p6 w/o mtrr's? */
135
jz .L_cpu_detect_asm_IsP5
137
/* Check for katmai-ness (bit 25) */
138
test $0x2000000 , %edx
139
jz .L_cpu_detect_asm_noKNI
142
jmp .L_cpu_detect_asm_DoneCpu /* return */
144
.L_cpu_detect_asm_noKNI:
146
jmp .L_cpu_detect_asm_DoneCpu /* return */
148
.L_cpu_detect_asm_IsP5:
150
jmp .L_cpu_detect_asm_DoneCpu
152
.L_cpu_detect_asm_NotPentium:
155
.L_cpu_detect_asm_DoneCpu:
163
.L_cpu_detect_asm_NotIntel:
165
/* This is a non-Intel processor. Figure out whether it supports */
166
/* both MMX and 3DNow!, in which case we can use Norbert's cool */
167
/* MMX/3DNow!(tm) code */
169
/* The return value is split into two 16-bit fields. Bits [31:16] */
170
/* identify the processor vendor as follows: */
176
/* Bits [15:0] identify processor features as follows: */
179
/* 0002h 3DNow! (tm) */
180
/* 0004h K6-style MTRRs */
181
/* 0008h PentiumII-style MTRRs */
183
xor %esi , %esi /* default feature flags */
184
xor %edi , %edi /* default extended feature flags */
186
/* Test whether extended feature function is supported */
188
mov $0x80000000 , %eax
190
cmp $0x80000000 , %eax
191
jbe .L_cpu_detect_asm_NoExtendedFeatures
193
/* execute extended feature function */
195
mov $0x80000001 , %eax
199
.L_cpu_detect_asm_NoExtendedFeatures:
201
/* execute standard feature function */
206
mov %eax , %ebp /* save family/model/stepping */
208
/* get the vendor string */
213
.L_cpu_detect_asm_ChkAMD:
214
cmp $0x68747541 , %ebx /* 'htuA' */
215
jne .L_cpu_detect_asm_ChkCyrix
216
cmp $0x69746E65 , %edx /* 'itne' */
217
jne .L_cpu_detect_asm_ChkCyrix
218
cmp $0x444D4163 , %ecx /* 'DMAc' */
219
je .L_cpu_detect_asm_CPUisAMD
221
.L_cpu_detect_asm_ChkCyrix:
222
cmp $0x69727943 , %ebx /* 'iryC' */
223
jne .L_cpu_detect_asm_ChkIDT
224
cmp $0x736E4978 , %edx /* 'snIx' */
225
jne .L_cpu_detect_asm_ChkIDT
226
cmp $0x64616574 , %ecx /* 'deat' */
227
je .L_cpu_detect_asm_CPUisCyrix
229
.L_cpu_detect_asm_ChkIDT:
230
cmp $0x746E6543 , %ebx /* 'tneC' */
231
jne .L_cpu_detect_asm_UnknownVendor
232
cmp $0x48727561 , %edx /* 'Hrua' */
233
jne .L_cpu_detect_asm_UnknownVendor
234
cmp $0x736C7561 , %ecx /* 'slua' */
235
jne .L_cpu_detect_asm_UnknownVendor
237
.L_cpu_detect_asm_CPUisIDT:
238
mov $0x80030000 , %eax /* vendor = IDT, features = none */
239
test $0x00800000 , %esi /* check for MMX bit in features */
240
jz .L_cpu_detect_asm_DoneCpu
241
or $1 , %eax /* set MMX feature flag */
242
test $0x80000000 , %edi /* check for 3DNow! bit in extended features */
243
jz .L_cpu_detect_asm_DoneCpu
244
or $2 , %eax /* set 3DNow! feature flag */
245
jmp .L_cpu_detect_asm_DoneCpu
247
.L_cpu_detect_asm_CPUisAMD:
248
mov $0x80010000 , %eax /* vendor = AMD, features = none */
249
mov %ebp , %edx /* family/model/stepping information */
250
and $0x00000FFF , %edx /* extract family/model/stepping */
251
cmp $0x00000588 , %edx /* CXT, Sharptooth, or K7 ? */
252
jb .L_cpu_detect_asm_AmdMTRRchkDone /* nope, definitely no MTRRs */
253
cmp $0x00000600 , %edx /* K7 or better ? */
254
jb .L_cpu_detect_asm_AmdHasK6MTRR /* nope, but supports K6 MTRRs */
255
or $8 , %eax /* set P2_MTRR feature flag */
256
jmp .L_cpu_detect_asm_AmdMTRRchkDone
257
.L_cpu_detect_asm_AmdHasK6MTRR:
258
or $4 , %eax /* set K6_MTRR feature flag */
259
.L_cpu_detect_asm_AmdMTRRchkDone:
260
test $0x00800000 , %esi /* check for MMX bit in features */
261
jz .L_cpu_detect_asm_DoneCpu
262
or $1 , %eax /* set MMX feature flag */
263
test $0x80000000 , %edi /* check for 3DNow! bit in extended features */
264
jz .L_cpu_detect_asm_DoneCpu
265
or $2 , %eax /* set 3DNow! feature flag */
266
jmp .L_cpu_detect_asm_DoneCpu
268
.L_cpu_detect_asm_CPUisCyrix:
269
mov $0x80020000 , %eax /* vendor = Cyrix, features = none */
270
test $0x00800000 , %esi /* check for MMX bit in features */
271
jz .L_cpu_detect_asm_DoneCpu
272
or $1 , %eax /* set MMX feature flag */
273
test $0x80000000 , %edi /* check for 3DNow! bit in extended features */
274
jz .L_cpu_detect_asm_DoneCpu
275
or $2 , %eax /* set 3DNow! feature flag */
276
jmp .L_cpu_detect_asm_DoneCpu
278
.L_cpu_detect_asm_UnknownVendor:
279
mov $0x0ffffffff , %eax
280
jmp .L_cpu_detect_asm_DoneCpu
283
.L_END__cpu_detect_asm:
284
.size _cpu_detect_asm,.L_END__cpu_detect_asm-_cpu_detect_asm
287
/* ------------------------------------------------------------------------------ */
288
/* this routine sets the precision to single */
289
/* which effects all adds, mults, and divs */
291
.globl single_precision_asm
292
.type single_precision_asm,@function
293
single_precision_asm:
294
push %eax /* make room */
295
fnclex /* clear pending exceptions */
298
and $0x0000fcff , %eax /* clear bits 9:8 */
303
.L_END_single_precision_asm:
304
.size single_precision_asm,.L_END_single_precision_asm-single_precision_asm
306
/* ------------------------------------------------------------------------------ */
307
/* this routine sets the precision to double */
308
/* which effects all adds, mults, and divs */
310
.globl double_precision_asm
311
.type double_precision_asm,@function
312
double_precision_asm:
313
push %eax /* make room */
314
fnclex /* clear pending exceptions */
317
and $0x0000fcff , %eax /* clear bits 9:8 */
318
or $0x000002ff , %eax /* set 9:8 to 10 */
323
.L_END_double_precision_asm:
324
.size double_precision_asm,.L_END_double_precision_asm-double_precision_asm