; * CPUA.ASM - Contains CPU detection and other functions. ; * Copyright (C) 1998, 1999 Prashant TR ; * ; * This program is free software; you can redistribute it and/or modify ; * it under the terms of the GNU General Public License as published by ; * the Free Software Foundation; either version 2 of the License, or ; * (at your option) any later version. ; * ; * See the file COPYING.TR for more details. ; Assembly functions to get CPU information. ; Externals. EXTRN _cpu__vendor ; Define global functions. PUBLIC _get_cpu_family PUBLIC _get_cpu_model PUBLIC _get_cpu_stepping_id PUBLIC _get_cpu_feature_flags PUBLIC _has_idflag PUBLIC _is_386dx PUBLIC _is_486dx PUBLIC _is_cyrix486 PUBLIC _get_cpu_vendor_name PUBLIC _get_cpu_value PUBLIC _get_xeon_celeron_p2d _TEXT SEGMENT BYTE PUBLIC 'CODE' ASSUME CS:_TEXT .386P ; To get CPU family. _get_cpu_family PROC FAR PUSH EBX ; Check for ID flag. PUSHFD POP EAX OR EAX, 200000H PUSH EAX POPFD PUSHFD POP EAX TEST EAX, 200000H JZ _family_no_cpuid ; Execute "cpuid". PUSH ECX PUSH EDX XOR EAX, EAX INC EAX DB 0FH, 0A2H POP EDX POP ECX MOV EBX, EAX XOR EAX, EAX ; Get the CPU family. MOV AL, BH POP EBX AND AL, 0FH XOR DX, DX RET _family_no_cpuid: ; Check AC flag. PUSHFD POP EAX MOV EAX, EBX XOR EAX, 40000H PUSH EAX POPFD PUSHFD POP EAX XOR EAX, EBX ; Pop out previously pushed ebx. POP EBX TEST EAX, 40000H MOV EAX, 4 JZ _family_cpu_386 ; CPU is 486. XOR DX, DX RET ; CPU is 386. _family_cpu_386: DEC EAX XOR DX, DX RET _get_cpu_family ENDP ; Get CPU model. _get_cpu_model PROC FAR PUSH EBX PUSH ECX PUSH EDX XOR EAX, EAX INC EAX DB 0FH, 0A2H POP EDX POP ECX POP EBX SHR EAX, 4 AND EAX, 0FH XOR DX, DX RET _get_cpu_model ENDP ; Get CPU stepping ID. _get_cpu_stepping_id PROC FAR PUSH EBX PUSH ECX PUSH EDX XOR EAX, EAX INC EAX DB 0FH, 0A2H POP EDX POP ECX POP EBX AND EAX, 0FH XOR DX, DX RET _get_cpu_stepping_id ENDP ; Get CPU feature flags. _get_cpu_feature_flags PROC FAR PUSH EBX PUSH ECX XOR EAX, EAX INC EAX DB 0FH, 0A2H MOV EAX, EDX SHR EDX, 16 POP ECX POP EBX RET _get_cpu_feature_flags ENDP ; To check if CPU has ID flag. _has_idflag PROC FAR PUSHFD POP EAX OR EAX, 200000H PUSH EAX POPFD PUSHFD POP EAX TEST EAX, 200000H JZ _idflag_no_cpuid XOR EAX, EAX INC EAX XOR DX, DX RET _idflag_no_cpuid: XOR EAX, EAX XOR DX, DX RET _has_idflag ENDP ; To check if a 386 CPU is DX / SX. _is_386dx PROC FAR PUSH EBX PUSH ECX MOV EAX, CR0 MOV EBX, EAX AND AL, 0EFH MOV CR0, EAX MOV ECX, CR0 MOV CR0, EBX CMP EAX, ECX POP ECX POP EBX JZ _386dx_is386sx XOR EAX, EAX INC EAX XOR DX, DX RET _386dx_is386sx: XOR EAX, EAX XOR DX, DX RET _is_386dx ENDP ; To check if a 486 CPU is DX / SX. _is_486dx PROC FAR FNINIT MOV AX, 0AA55H ; FNSTSW AX DB 0DFH, 0E0H JMP _486dx_jmp1 _486dx_jmp1: JMP _486dx_jmp2 _486dx_jmp2: OR AX, AX JNZ _486dx_is486sx XOR EAX, EAX INC EAX XOR DX, DX RET _486dx_is486sx: XOR EAX, EAX XOR DX, DX RET _is_486dx ENDP ; To check if we are on a Cyrix 486. _is_cyrix486 PROC FAR MOV AX, 5 SAHF DIV AL LAHF CMP AH, 2 JZ _cyrix486_iscyrix486 XOR EAX, EAX XOR DX, DX RET _cyrix486_iscyrix486: XOR EAX, EAX INC EAX XOR DX, DX RET _is_cyrix486 ENDP ; To get CPU vendor name. _get_cpu_vendor_name PROC FAR PUSHAD PUSH DS XOR EAX, EAX DB 0FH, 0A2H MOV AX, SEG _cpu__vendor MOV DS, AX MOV SI, OFFSET _cpu__vendor MOV [SI + 8], ECX MOV [SI + 4], EDX MOV [SI], EBX POP DS POPAD MOV DX, SEG _cpu__vendor MOV AX, OFFSET _cpu__vendor RET _get_cpu_vendor_name ENDP _get_cpu_value PROC FAR PUSH EBX PUSH ECX PUSH EDX XOR EAX, EAX INC EAX DB 0FH, 0A2H POP EDX POP ECX POP EBX MOV DX,AX SHR EAX, 16 XCHG DX, AX XOR DX, DX RET _get_cpu_value ENDP _get_xeon_celeron_p2d PROC FAR ; Assume celeron if in protected mode. SMSW AX TEST AL, 1 JNZ _celeron MOV ECX, 11EH DB 0FH, 32H ; RDMSR TEST EAX, 800000H JZ _p2d_test1 ; Celeron. _celeron: POPAD MOV AX, 1 RET _p2d_test1: SHR EAX, 0DH TEST AL, 1FH JNZ _p2d_test2 ; Celeron. JMP _celeron _p2d_test2: POPAD MOV AX, 2 RET _get_xeon_celeron_p2d ENDP _TEXT ENDS END