VERIFY_NOT_OTHER_STRING	equ	1
;VERIFY_AMD_STRING	equ	1

sCpuID	STRUC
	MaxStdFunc	dd	?
	MaxExtFunc	dd	?
	FuncS1Flags	dd	?
	FuncX1Flags	dd	?
	ProcSig		dd	?
	XProcSig	dd	?
	ProcNameString	dd	12 dup (?)
	CacheInfo	dd	3 dup (?)
	CpuString	db	13 dup (?)
sCpuID	ENDS

_DATA	SEGMENT
	_CpuStruct	sCpuID	<>
	OtherString	db	'GenuineIntel',0
	AmdString	db	'AuthenticAMD',0
_DATA	ENDS

_TEXT	SEGMENT

PUBLIC	_CpuStruct
PUBLIC	_GetCpuId

_GetCpuId	proc

	push		ebp
	mov		ebp, esp
	
	push		ebx
	push		ecx
	push		edx
	push		esi
	push		edi
	pushfd
	
;	mov		edi, [ebp+8]	; Get structure pointer
	lea		edi, [_CpuStruct] 	; Get structure pointer
	push		edi
	
	mov		ecx, size sCpuID
	mov		al, 0
	rep		stosb		; Zero out the structure

	pop		edi

; Ensure that the CPUID instruction is supported by this CPU by checking
; the "writeability" of bit 21 (ID bit) in EFLAGS
	pushfd 
	pop		eax 
	mov		ebx, eax 
	xor		eax, 00200000h 
	push		eax 
	popfd 
	pushfd 
	pop		eax 
	cmp		eax, ebx 
	jz		NoCpuIdSupport

; CPUID Function 0 [EAX] returns the maximum supported standard function number
; and the mfg. string.
; We need at least standard function level 1 support to continue...
	mov		eax, 0 
	cpuid

	cmp		eax, 1
	jb		NoStdFunc01

	mov		[edi].MaxStdFunc, eax
	mov		dword ptr [edi+0].CpuString, ebx
	mov		dword ptr [edi+4].CpuString, edx
	mov		dword ptr [edi+8].CpuString, ecx
	mov		byte ptr [edi+12].CpuString, 0	; Null terminate the string.
	push		edi
	push		ecx
	mov		ecx, 3
	lea		edi, [edi].CpuString

ifdef	VERIFY_AMD_STRING
	lea		esi, [AmdString]
	rep		cmpsd
	jnz		WrongCpu
endif

ifdef	VERIFY_NOT_OTHER_STRING
	lea		esi, [OtherString]
	rep		cmpsd
	jz		WrongCpu
endif
	pop		ecx
	pop		edi
;;; Std Function 1
	mov		eax, 1
	cpuid
	mov		[edi].FuncS1Flags, edx
	mov		[edi].ProcSig, eax
	
;;; Ext Function 0
	mov		eax, 080000000h	; Check for support of extended functions
	cpuid
	cmp		eax, 80000001h
	jb		CantBe3DNowCpu

	mov		[edi].MaxExtFunc, eax

;;; Ext Function 1

	mov		eax, 80000001h	; Prepare for CPUID "Get extended features"
	cpuid
	mov		[edi].FuncX1Flags, edx
	mov		[edi].XProcSig, eax
	test		edx, 80000000h		; 3DNow! instruction support
	jz		CantBe3DNowCpu
	
Is3DNowCpu:
	mov		eax, 0

AmdReturn:
	popfd
	pop		edi
	pop		esi
	pop		edx
	pop		ecx
	pop		ebx
	pop		ebp
	ret

NoCpuIdSupport:
	mov		eax, -1
	jmp		AmdReturn

NoStdFunc01:
	mov		eax, -2
	jmp		AmdReturn

WrongCpu:
	pop		ecx
	pop		edi
	mov		eax, -3
	jmp		AmdReturn

CantBe3DNowCpu:
	mov		eax, -4
	jmp		AmdReturn

_GetCpuId	endp

_TEXT	ENDS
