;* Procdi.asm - Processor Identification routines ;* ;* (C) Copyright Microsoft Corp., 1995 ;* ;* Processor ID ;* ;* Origin: ;* ;* Change history: ;* ;* Date Who Description ;* --------- --------- ------------------------------------------------- ;* 12-Oct-95 MikeG Created ;* .386p .387 .model flat ;************************** Include Files ************************ ; include winbase.inc ; include winerror.inc ; include kernel32.inc ; include segs.inc ; include regstr.inc ;******************** Data Declerations ************************** .data _DATA SEGMENT CPU_ID macro db 0fh, 0a2h endm NONE equ 0 PRESENT equ 1 Nx586 equ 5 UNKNOWN equ 0 _nxcpu db NONE ;default to none _cputype db UNKNOWN ;default to unknown _cpuid_flag db NONE ;default to no CPUID _vendor_id db "************" _cpu_signature dd 0 _features_ecx dd 0 _features_edx dd 0 _features_ebx dd 0 NexGen_id db "NexGenDriven" ;*********************** Prototypes ****************************** ;************************** Code ********************************* .code _TEXT SEGMENT ;========================================================================== ; _get_nxcpu_type ; This routine identifies NexGen's processor type in following steps: ; ; if (no AC flag) { //current Nx586 does not support AC flag ; set ZF=1; ; execute DIV to result a none zero value; ; if (ZF=0) { //ZF is changed ; not a NexGen processor; ; exit; ; } else { //Nx586 does not change ZF on DIV instruction ; if (ID bit not writeable) { ; CPU is Nx586 with no CPUID support ; } else { //Nx586 with CPUID support ; execute CPUID instruction; ; save CPU information; ; } ; } ; } else { ; if (ID bit not writeable) { ; not a NexGen processor; ; } else { //NexGen future processors support CPUID ; execute CPUID instruction; ; save CPU information; ; } ; } ; ;========================================================================== get_nxcpu_type proc C cdecl:DWORD push ebx push esi push edi mov byte ptr _nxcpu,PRESENT ; default to present ; test AC bit on EFLAGS register mov bx,sp ; save the current stack pointer and sp,not 3 ; align the stack to avoid AC fault pushfd ; pop eax ; get the original EFLAGS mov ecx,eax ; save original flag xor eax,40000h ; flip AC bit in EFLAGS push eax ; save for EFLAGS popfd ; copy it to EFLAGS pushfd ; pop eax ; get the new EFLAGS value mov sp,bx ; restore stack pointer xor eax,ecx ; if the AC bit is unchanged je test_zf ; goto second step jmp nx_future_cpu test_zf: ; test ZF on DIV instruction mov ax,5555h ; init AX with a non-zero value xor dx,dx ; set ZF=1 mov cx,2 div cx ; Nx586 processor does not modify ZF on DIV jnz not_nx_cpu ; not a NexGen processor if ZF=0 (modified) test_cpuid: ; test if CPUID instruction is available ; new Nx586 or future CPU supports CPUID instruction pushfd ; get EFLAGs pop eax mov ecx,eax ; save it xor eax,200000h ; modify ID bit push eax popfd ; save it in new EFLAGS pushfd ; get new EFLAGS pop eax ; xor eax,ecx ; is ID bit changed? jnz cpuid_present ; yes mov byte ptr _cputype,Nx586 ; no, current Nx586 mov eax,1 ; set return code == true jz cpuid_exit ; stop testing nx_future_cpu: ; all NexGen's future processors feature a CPUID instruction mov eax,ecx ; get original EFLAGS xor eax,200000h ; modify ID bit push eax popfd ; save it in new EFLAGS pushfd ; get new EFLAGS pop eax ; xor eax,ecx ; is ID bit changed? jz not_nx_cpu ; no, not a NexGen processor cpuid_present: ; execute CPUID instruction to get vendor name, stepping and feature info xor eax,eax CPU_ID mov dword ptr _vendor_id,ebx mov dword ptr _vendor_id[+4],edx mov dword ptr _vendor_id[+8],ecx mov bx,ds mov es,bx mov esi,offset _vendor_id mov edi,offset NexGen_id mov cx,12 cld repe cmpsb ; compare vendor ID string jne not_nx_cpu mov byte ptr _cpuid_flag,PRESENT cmp eax,1 ; check highest level jl cpuid_exit mov eax,1 CPU_ID mov _cpu_signature,eax mov _features_ecx,ecx mov _features_edx,edx mov _features_ebx,ebx shr eax,8 and al,0fh mov _cputype,al jmp cpuid_exit not_nx_cpu: mov byte ptr _nxcpu,NONE xor eax,eax cpuid_exit: pop edi pop esi pop ebx ret get_nxcpu_type endp ;************************************************************************** ; Function: int is_cyrix () ; ; Purpose: Determine if Cyrix CPU is present ; Technique: Cyrix CPUs do not change flags where flags change ; in an undefined manner on other CPUs ; Inputs: none ; Output: ax == 1 Cyrix present, 0 if not ;************************************************************************** is_cyrix proc C __cdecl:WORD .486 push bx xor ax, ax ; clear ax sahf ; clear flags, bit 1 is always 1 in flags mov ax, 5 mov bx, 2 div bl ; do an operation that does not change flags lahf ; get flags cmp ah, 2 ; check for change in flags jne not_cyrix ; flags changed not Cyrix mov ax, 1 ; TRUE Cyrix CPU jmp done not_cyrix: mov ax, 0 ; FALSE NON-Cyrix CPU done: pop bx ret is_cyrix endp _TEXT ends end