reman3/Rayman_X/cpa/tempgrp/Tmr/specif/Detect.c

277 lines
6.7 KiB
C

#include "string.h"
#include "detect.h"
long CPUINFO;
char cIDENT[13];
/***********************************/
/* VISUAL 5 CPU detection function */
/***********************************/
#ifndef WATCOM
#define CPUID __asm _emit 0x0F __asm _emit 0x0a2
#define RDTSC __asm _emit 0x0F __asm _emit 0x31
long gIsCpuidSupported(void)
{
long retour;
_asm{
pushfd
pop eax
test eax,0x00200000
jz bit21
and eax,0xffdfffff
push eax
popfd
pushfd
pop eax
test eax,0x00200000
jz ok
jmp no_ok
bit21:
or eax,0x00200000
push eax
popfd
pushfd
pop eax
test eax,0x00200000
jnz ok
jmp no_ok
ok:
mov eax,1
jmp done
no_ok:
mov eax,0
done:
mov retour,eax
}
return retour;
}
long gCPUInfo()
{
long retour;
_asm{
mov eax,1
CPUID
mov retour, eax
}
return retour;
}
void gBuilderIdent(void)
{
_asm{
mov eax,0
CPUID
mov word ptr[cIDENT],bx
shr ebx,16
mov word ptr[cIDENT+2],bx
mov word ptr[cIDENT+4],dx
shr edx,16
mov word ptr[cIDENT+6],dx
mov word ptr[cIDENT+8],cx
shr ecx,16
mov word ptr[cIDENT+10],cx
}
}
#else
/***********************************/
/* WATCOM CPU detection function */
/***********************************/
long gIsCpuidSupported();
#pragma aux gIsCpuidSupported = \
"pushfd"\
"pop eax"\
"test eax,0x00200000"\
"jz bit21"\
"and eax,0xffdfffff"\
"push eax"\
"popfd"\
"pushfd"\
"pop eax"\
"test eax,0x00200000"\
"jz ok"\
"jmp no_ok"\
"bit21:"\
"or eax,0x00200000"\
"push eax"\
"popfd"\
"pushfd"\
"pop eax"\
"test eax,0x00200000"\
"jnz ok"\
"jmp no_ok"\
"ok:"\
"mov eax,1"\
"jmp done"\
"no_ok:"\
"mov eax,0"\
"done:"\
value [eax]\
modify [eax ebx ecx edx esi edi];
long gCPUInfo();
#pragma aux gCPUInfo = \
"mov eax,1"\
"db 0x0F, 0xa2"\
value [eax]\
modify [eax ebx ecx edx];
void gBuilderIdent();
#pragma aux gBuilderIdent=\
"mov eax,0"\
"db 0x0F, 0xa2"\
"mov word ptr[cIDENT],bx"\
"shr ebx,16"\
"mov word ptr[cIDENT+2],bx"\
"mov word ptr[cIDENT+4],dx"\
"shr edx,16"\
"mov word ptr[cIDENT+6],dx"\
"mov word ptr[cIDENT+8],cx"\
"shr ecx,16"\
"mov word ptr[cIDENT+10],cx"\
modify [eax ebx ecx edx];
#endif
/**********************************/
/* Return 1 if RDTSC is available */
/**********************************/
long fn_lIsRdtscAvailable()
{
long Cpu_Type = UNKNOWN;
char cModel = (char)0xFF;
long lRdtscOk = 0;
if (gIsCpuidSupported())
{
CPUINFO = gCPUInfo();
gBuilderIdent();
if ( strcmp(cIDENT, "GenuineIntel") ==0 )
{
/* Family*/
switch ((CPUINFO&0xF00)>>8)
{
case 4:
if ( ((CPUINFO&0xF0)>>4) == 7)
Cpu_Type = iDX2;
else if ( ((CPUINFO&0xF0)>>4) == 8)
Cpu_Type = iDX4;
else
Cpu_Type = UNKNOWN;
break;
case 5:
Cpu_Type = PENTIUM;
if ( ((CPUINFO&0xF0)>>4) == 4) Cpu_Type = PENT_MMX;
lRdtscOk = 1;
break;
case 6:
case 15:
Cpu_Type = PENTIUM_PRO;
if ( ((CPUINFO&0xF0)>>4) == 3) Cpu_Type = PENTIUM2;
lRdtscOk = 1;
break;
default:
Cpu_Type = UNKNOWN;
break;
}
}
else if ( strcmp(cIDENT, "AuthenticAMD") ==0 )
{
switch (CPUINFO & 0x00000FF0)
{
case 0x0500 :
case 0x0510 :
Cpu_Type = AMD_K5;
cModel = (CPUINFO & 0x030) >> 4;
break;
case 0x0520 :
case 0x0530 :
Cpu_Type = AMD_K5;
cModel = (CPUINFO & 0x030) >> 4;
lRdtscOk = 1;
break;
case 0x0560 :
case 0x0570 :
case 0x0580 :
case 0x0590 :
Cpu_Type = AMD_K6;
cModel = (CPUINFO & 0x0F0) >> 4;
lRdtscOk = 1;
break;
case 0x06A0 :
// Athlon! But pretend it's a K6 so the timers work...
Cpu_Type = AMD_K6;
cModel = (CPUINFO & 0x0F0) >> 4;
lRdtscOk = 1;
break;
default:
if ( (CPUINFO&0xF00) == 0x400)
Cpu_Type = Am5x86;
else
Cpu_Type = UNKNOWN;
break;
}
}
else if (strcmp(cIDENT, "CyrixInstead") ==0 ) /* CYRIX */
{
switch ((CPUINFO&0xF00)>>8) /* Family */
{
case 4:
if ( ((CPUINFO&0xF0)>>4) == 4 )
Cpu_Type = MediaGX;
break;
case 5:
switch ((CPUINFO&0xF0)>>4) /* Model */
{
case 2:
Cpu_Type = CX_6X86;
break;
case 4:
Cpu_Type = GXm;
break;
}
break;
case 6:
Cpu_Type = CX_6x86MX;
lRdtscOk = 1;
break;
default:
Cpu_Type = UNKNOWN;
break;
}
}
else if (strcmp(cIDENT, "CentaurHauls")==0) /* IDT */
{
Cpu_Type = IDT_C6;
}
}
return (lRdtscOk);
}