Tvùrce webu je i pro tebe! Postav tøeba web. Bez grafika. Bez kodéra. Hned.
wz

INIT_CPU.ASM

Initialize CPU


; =============================================================================
;
;                    Litos - Initialize CPU, protected mode
;
; =============================================================================

%ifdef DEBUG
;%define	DEBUG_CPU		; uncomment this to display CPU info
%endif

		CODE_SECTION	32

; ------------- Macro - test if Time-Stamp Counter is supported (NZ=supported)

%define		TSC_OK	test byte [CPUInfo+CPU_Features],B4

; ------------- CPU information for Intel (i386) architecture

struc		CPUINFO

CPU_Type:	resb	1		; 0: CPU basic type
CPU_Family:	resb	1		; 1: CPU family
CPU_Model:	resb	1		; 2: CPU model
CPU_VendorID:	resb	1		; 3: CPU vendor ID
CPU_Vendor:	resb	12		; 4: vendor name (12 characters)
CPU_Flags:	resd	1		; 10h: flags
					;  B0: multiprocessor
					;  B1: MMX supported
					;  B2: SSE supported
					;  B3: SSE2 supported
					;  B4: 3DNow! supported
					;  B5: 3DNow! Extended supported
					;  B6: MMX+ AMD extension supported
					;  B7: MMX+ Cyrix extension supported
					;  B8: FPU coprocessor present
					;  B9: FPU coprocessor is emulated
CPU_Features:	resd	1		; 14h: features (reported by CPU)
					;  B0: (FPU) floating point unit
					;  B1: (VME) virtual mode enhancement
					;  B2: (DE) debugging extensions
					;  B3: (PSE) page size extensions
					;  B4: (TSC) time stamp counter
					;  B5: (MSR) model-specific registers
					;  B6: (PAE) physical address extens.
					;  B7: (MCE) machine check exceptions
					;  B8: (CX8) CMPXCHG8B instruction
					;  B9: (APIC) APIC on chip
					;  B10: ...reserved
					;  B11: (SEP) fast system calls
					;  B12: (MTRR) mem.type range registers
					;  B13: (PGE) PTE page global bit enab.
					;  B14: (MCA) machine check architect.
					;  B15: (CMOV) condit.move/comp.instr.
					;  B16: (PAT) page attribute table
					;  B17: (PSE) 36-bit page size extens.
					;  B18: (PSN) processor serial number
					;  B19: (CLFSH) CFLUSH instruction
					;  B20: ...reserved
					;  B21: (DS) debug store
					;  B22: (ACPI) thermal mon.+clock ctrl.
					;  B23: (MMC) MMX instruction set
					;  B24: (FXSR) FXSAVE/FXRSTOR instruct,
					;  B25: (SSE) SSE extensions
					;  B26: (SSE2) SSE2 extensions
					;  B27: (SS) self snoop
					;  B28: (HTT) hyper-threading technol.
					;  B29: (TM) thermal monitor
					;  B30: (IA-64) IA-64(64-bit Intel CPU)
					;  B31: (PBE) pending break event
CPU_Extended:	resd	1		; 18h: extended features (vendor depen.)
					;  B10: AMD K6 model 6: Fast Syst.Calls
					;  B11: AMD K6 model 7 or newer:
					; 		Fast System Calls
					;  B16: (fcmov) Cyrix, AMD K6 CPUs:
					;	Floating-point Conditional Move
					;       (pat) AMD K7 CPUs:
					;		Page Attribute Table
					;  B19: (mp) MP(MultiProcessor) Capable
					;  B22: (mmx+) AMD: MMX+ (AMD MMX Ext.)
					;  B24: (cxmmx) Cyrix: Extended MMX
					;       (fxsr) AMD K7:
					;	Fast float. point save/restore
					;  B29: (lm) AA-64 (AMD 64-bit CPU)
					;  B30: (3dnowext) 3DNow! extended
					;  B31: (3dnow) 3DNow! instructions
CPU_Frequency:	resd	1		; 1Ch: CPU frequency in Hz (min. 2 MHz)

endstruc				; size 20h = 32 bytes

; ------------- CPU flags

CPU_SMP		EQU	B0		; multiprocessor
CPU_MMX		EQU	B1		; MMX supported
CPU_SSE		EQU	B2		; SSE supported
CPU_SSE2	EQU	B3		; SSE2 supported
CPU_3DNOW	EQU	B4		; 3DNow! supported
CPU_3DNOW2	EQU	B5		; 3DNow! Extended supported
CPU_MMXAMD	EQU	B6		; MMX+ AMD extension supported
CPU_MMXCYR	EQU	B7		; MMX+ Cyrix extension supported
CPU_FPU		EQU	B8		; FPU coprocessor present
CPU_EMU		EQU	B9		; FPU coprocessor is emulated

; ------------- CPU architecture

CPU_ARCH_GENER	EQU	0		; generic CPU
CPU_ARCH_INTEL	EQU	1		; Intel (i386)

; ------------- CPU basic type - Intel architecture

CPU_8086	EQU	0		; 8086 (unsupported)
CPU_186		EQU	1		; 80186 (unsupported)
CPU_286		EQU	2		; 80286 (unsupported)
CPU_386		EQU	3		; 80386
CPU_486		EQU	4		; 80486
CPU_PENTIUM	EQU	5		; Pentium
CPU_PENTIUM2	EQU	6		; Pentium 2, Pentium Pro
CPU_PENTIUM3	EQU	7		; Pentium 3
CPU_PENTIUM4	EQU	8		; Pentium 4

; ------------- CPU vendor ID

CPU_VEND_GENER	EQU	0		; generic or unknown
CPU_VEND_INTEL	EQU	1		; Intel		("GenuineIntel")
CPU_VEND_AMD	EQU	2		; AMD		("AuthenticAMD")
CPU_VEND_CYRIX	EQU	3		; Cyrix		("CyrixInstead")
CPU_VEND_CENT	EQU	4		; Centaur	("CentaurHauls")
CPU_VEND_NEXGEN	EQU	5		; NexGen	("NexGenDriven")
CPU_VEND_TRANS	EQU	6		; Transmeta	("GenuineTMx86")
CPU_VEND_RISE	EQU	7		; Rise		("RiseRiseRise")
CPU_VEND_UMC	EQU	8		; UMC		("UMC UMC UMC ")
CPU_VEND_SIS	EQU	9		; SiS		("SiS SiS SiS ")
CPU_VEND_NSC	EQU	10		; National Semiconductor
					;		("Geode by NSC")
CPU_VEND_NUM	EQU	11		; number of vendor ID codes

; ------------- CPU family and model variants:
;    Family:   Model:      Name:
;	0	0	8086 (unsupported)
;	1	0	80186 (unsupported)
;	2	0	80286 (unsupported)
;	3	1	80386 DX
;		2	80386 SX
; -------------
; Intel:
;    Family:   Model:      Name:
;	4	0	486 DX-25/33
;		1	486 DX-50
;		2	486 SX
;		3	486 DX/2
;		4	486 SL
;		5	486 SX/2
;		7	486 DX/2-WB
;		8	486 DX/4
;		9	486 DX/4-WB
;	5	0	Pentium 60/66 A-step
;		1	Pentium 60/66
;		2	Pentium 75 - 200
;		3	OverDrive PODP5V83
;		4	Pentium MMX
;		7	Mobile Pentium 75 - 200
;		8	Mobile Pentium MMX
;	6	0	Pentium Pro A-step
;		1	Pentium Pro
;		3	Pentium II (Klamath)
;		5	Pentium II (Deschutes), Celeron (Covington),
;			Mobile Pentium II (Dixon)
;		6	Mobile Pentium II, Celeron (Mendocino)
;		7	Pentium III (Katmai)
;		8	Pentium III (Coppermine)
;		9	Mobile Pentium III
;		10	Pentium III (0.18 um) (Cascades)
;		11	Pentium III (0.13 um) (Tualatin)
;		13	Mobile Pentium III 2 MB (0.09 um)
;		14	Mobile Pentium III DC (65 nm) 2 MB
;		15	Core 2 DC (65 nm) 4 MB
;	7	..	Itanium (IA-64)
;	16	0	Pentium IV (0.18 um)
;		1	Pentium IV (0.13 um) (Willamette)
;		2	Pentium IV (0.13 um) (Northwood)
;		3	Pentium IV (0.09 um)
;		4,5	Pentium IV (Foster)
;	17	..	Itanium 2 (IA-64)
;	18	?	Itanium 2 DC (IA-64)
; -------------
; AMD:
;    Family:   Model:      Name:
;	4	3	486 DX/2
;		7	486 DX/2-WB
;		8	486 DX/4
;		9	486 DX/4-WB
;		14	Am5x86-WT
;		15	Am5x86-WB
;	5	0	K5/SSA5
;		1..3	K5
;		6,7	K6
;		8	K6-2
;		9	K6-3
;		13	K6-2+ or K6-III+
;	6	0,1	Athlon (25 um)
;		2	Athlon (18 um)
;		3	Duron
;		4	Athlon (Thunderbird)
;		6	Athlon (Palamino)
;		7	Duron (Morgan)
;		8	Athlon (Thoroughbred)
;		10	Athlon (Barton)
;	16	4	Athlon 64
;		5	Athlon 64 FX
;			Opteron
;		?	K8 (130 nm)
;	17	?	K8 (90 nm Rev D)
;	18	?	K8 (90 nm Rev E)
;	20	?	K8 (90 nm Rev F)
; -------------
; Cyrix:
;    Family:   Model:      Name:
;	4	4	MediaGX
;	5	2	6x86 / 6x86L
;		4	MediaGX MMX Enhanced 
;	6	0	m II (6x86MX)
;		5	VIA Cyrix M2 core
;		6	WinChip C5A
;		7	WinChip C5B, WinChip C5C
;		8	WinChip C5N
;		9	WinChip C5XL, WinChip C5P
; -------------
; UMC:
;    Family:   Model:      Name:
;	4	1	U5D
;		2	U5S
; -------------
; NexGen:
;    Family:   Model:      Name:
;	5	0	Nx586
; -------------
; Rise
;    Family:   Model:      Name:
;	5	0,1	mP6
; -------------
; SiS
;    Family:   Model:      Name:
;	5	0	55x
; -------------
;Transmeta
;    Family:   Model:      Name:
;	5	4	Crusoe TM3x00 and TM5x00
;	16	0	Efficeon
; -------------
; Centaur
;    Family:   Model:      Name:
;	5	4	C6 
;		8	C2
;		9	C3
; -------------
; National Semiconductor
;    Family:   Model:      Name:
;	5	4	GX1, GXLV, GXm
;	5	5	GX2

; -----------------------------------------------------------------------------
;                           Detect and init CPU
; -----------------------------------------------------------------------------

; ------------- Prepare information structure

InitCPU:	mov	esi,CPUInfo	; ESI <- CPU info structure
		mov	byte [esi+CPU_Type],CPU_386 ; 80386
		mov	byte [esi+CPU_Family],3 ; Family 80386
		inc	byte [esi+CPU_Model] ; Model 80386 DX

; ------------- Check CPU if it is 486 at least (486 can change AC flag bit)

		pushf			; push flags
		pushf			; push flags
		pop	eax		; EAX <- flags
		mov	ecx,eax		; ECX <- store flags
		xor	eax,B18+B21	; change bits AC and ID
		push	eax		; push EAX
		popf			; set new flags
		pushf			; push flags
		pop	eax		; EAX <- changed flags
		popf			; pop old flags
		xor	eax,ecx		; EAX <- changed bits
		test	eax,B18		; bit AC changed?
		jnz	InitCPU2	; bit AC can be changed, it is 486

; ------------- Check CPU if it is 386 SX (386 SX cannot change bit 4 of CR0)

		mov	eax,cr0		; EAX <- CR0
		mov	ecx,eax		; ECX <- push original CR0
		xor	al,B4		; change bit 4 (ET)
		mov	cr0,eax		; set new value into CR0
		mov	eax,cr0		; EAX <- new value
		mov	cr0,ecx		; CR0 <- return original value
		xor	eax,ecx		; EAX <- changed bits
		test	al,B4		; can be bit 4 changed?
		jnz	InitCPU1	; can be changed, it is 386 DX
		inc	byte [esi+CPU_Model] ; else it is 80386 SX
InitCPU1:	ret

; ------------- Check CPU if it is 486 SX (486 SX has no math coprocessor)

InitCPU2:	inc	byte [esi+CPU_Type] ; it is 486
		inc	byte [esi+CPU_Family] ; Family 80386
		test	byte [BIOSEquip],B1 ; is math coprocessor installed?
		jnz	InitCPU3	; math coprocessor is installed
		inc	byte [esi+CPU_Model] ; else it is 80486 SX

; ------------- Check if CPU supports CPUID information

InitCPU3:	test	eax,B21		; bit ID changed?
		jz	InitCPU1	; ID cannot be changed, it has not ID
		inc	byte [esi+CPU_Type] ; it is Pentium
		inc	byte [esi+CPU_Family] ; Family Pentium
		mov	byte [esi+CPU_Model],1 ; Model Pentium

; ------------- Get vendor name

		xor	eax,eax		; EAX <- 0 function code
		cpuid			; get vendor name
		mov	[esi+CPU_Vendor],ebx ; Vendor name 0 to 3
		mov	[esi+CPU_Vendor+4],edx ; Vendor name 4 to 7
		mov	[esi+CPU_Vendor+8],ecx ; Vendor name 8 to 11

; ------------- Find vendor ID (search vendor string)

		mov	byte [esi+CPU_VendorID],CPU_VEND_NUM-1 ; last ID
		mov	edi,CPUVendString+(CPU_VEND_NUM-2)*12 ; last string
InitCPU4:	cmp	ebx,[edi]	; check characters 0 to 3
		jne	InitCPU42	; not equal
        	cmp	edx,[edi+4]	; check characters 4 to 7
		jne	InitCPU42	; not equal
        	cmp	ecx,[edi+8]	; check characters 8 to 11
		je	InitCPU5	; found vendor
InitCPU42:	sub	edi,byte 12	; shift string pointer
		dec	byte [esi+CPU_VendorID] ; decrease vendor ID
		jnz	InitCPU4	; test next vendor string

; ------------- Get CPU information

InitCPU5:	or	eax,eax		; another information?
		jz	InitCPU1	; no other information
		mov	eax,1		; EAX <- 1 function code
		cpuid			; get CPU type

; ------------- CPU features

		mov	[esi+CPU_Features],edx ; store CPU features
		test	edx,B23		; MMX supported?
		jz	InitCPU52	; MMX not supported
		or	byte [esi+CPU_Flags],byte CPU_MMX ; MMX supported
InitCPU52:	test	edx,B25		; SSE supported?
		jz	InitCPU53	; SSE not supported
		or	byte [esi+CPU_Flags],CPU_SSE ; SSE supported
InitCPU53:	test	edx,B26		; SSE2 supported?
		jz	InitCPU56	; SSE2 not supported
		or	byte [esi+CPU_Flags],CPU_SSE2 ; SSE2 supported

; ------------- CPU family

InitCPU56:	mov	ecx,eax		; ECX <- push CPU version
		shr	eax,8		; EAX <- family
		and	al,0fh		; mask family
		cmp	al,15		; use extended family?
		jne	InitCPU6	; no, use base family
		shr	eax,20-8	; EAX <- extended family
		add	al,16		; AL <- extended family	
InitCPU6:	mov	[esi+CPU_Family],al ; store family

; ------------- CPU model

		xchg	eax,ecx		; EAX <- CPU version, CL <- family
		shr	eax,4		; EAX <- model
		and	al,0fh		; mask model
		cmp	cl,6		; supports extended model?
		jbe	InitCPU62	; doesn't support extended model
		cmp	al,15		; use extended model?
		jne	InitCPU62	; no, use base model
		shr	eax,16-4	; EAX <- extended model
		and	al,0fh		; mask extended model
		add	al,16		; AL <- extended model
InitCPU62:	mov	[esi+CPU_Model],al ; store model

; ------------- Detect Pentium CPU basic type

		cmp	cl,4		; 486?
		ja	InitCPU64	; no 486
		dec	byte [esi+CPU_Type] ; it is 80486
InitCPU64:	cmp	cl,5		; Pentium 1?
		jbe	InitCPU7	; Pentium 1
		inc	byte [esi+CPU_Type] ; Pentium 2
		cmp	cl,6		; Pentium Pro, 2 or 3?	
		ja	InitCPU65	; Pentium 4
		cmp	al,7		; Pentium 3?
		jb	InitCPU66	; Pentium 2 or 3
InitCPU65:	inc	byte [esi+CPU_Type] ; Pentium 3
InitCPU66:	cmp	cl,7		; Pentium 4?
		jb	InitCPU7	; no
		inc	byte [esi+CPU_Type] ; Pentium 4

; ------------- Extended features

InitCPU7:	mov	eax,80000000h	; EAX <- function code
		push	eax		; push EAX
                cpuid			; get max. function type
		pop	ecx		; ECX <- function code
		inc	ecx		; ECX <- function code+1
		cmp	eax,ecx		; is function 1 supported?
		jb	InitCPU9	; function 1 is not supported
		xchg	eax,ecx		; EAX <- function code
		cpuid			; get extended features
		mov	[esi+CPU_Extended],edx ; store extended features

; ------------- Check extended features

		test	edx,B31		; 3DNow supported?
		jz	InitCPU72	; 3DNow not supported
		or	byte [esi+CPU_Flags],CPU_3DNOW ; 3DNOW supported
InitCPU72:	test	edx,B30		; 3DNow2 supported?
		jz	InitCPU74	; 3DNow2 not supported
		or	byte [esi+CPU_Flags],CPU_3DNOW2 ; 3DNOW2 supported
InitCPU74:	cmp	byte [esi+CPU_VendorID],CPU_VEND_AMD ; AMD CPU?
		jne	InitCPU75	; no AMD
		test	edx,B22		; MMX+ AMD supported?
		jz	InitCPU75	; MMX+ AMD not supported
		or	byte [esi+CPU_Flags],CPU_MMXAMD ; MMX+ AMD supported
InitCPU75:	cmp	byte [esi+CPU_VendorID],CPU_VEND_CYRIX ; Cyrix CPU?
		jne	InitCPU9	; no Cyrix
		test	edx,B24		; MMX+ Cyrix supported?
		jz	InitCPU9	; MMX+ Cyrix not supported
		or	byte [esi+CPU_Flags],CPU_MMXCYR ; MMX+ Cyrix supported
InitCPU9:	ret

; -----------------------------------------------------------------------------
;                             Init math coprocessor
; -----------------------------------------------------------------------------

; ------------- Init CR0 register

InitFPU:	mov	eax,cr0		; EAX <- CR0
		and	eax,B31+B4+B0	; save PG, ET and PE bits
		or	eax,byte B1	; set MP bit (monitor coprocessor)
		cmp	byte [CPUInfo+CPU_Type],CPU_486 ; is 486 or more?
		jb	InitFPU2	; is 386
		or	eax,B18+B16+B5	; set AM, WP and NE flags, too
InitFPU2:	mov	cr0,eax		; set CR0

; ------------- Check if FPU is valid

		clts			; clear task-switched flag in CR0
		fninit			; initialize FPU
		fstsw	ax		; AX <- FPU status word
		or	al,al		; AL = 0?
		jz	InitFPU4	; coprocessor is OK

; ------------- Set EM flag (FPU is emulated)
; FPU emulator currently not supported
;		mov	eax,cr0		; EAX <- CR0
;		or	eax,byte B2	; set EM flag (FPU is emulated)
;		mov	cr0,eax		; CR0 <- EAX
;		or	byte [CPUInfo+CPU_Flags+1],CPU_EMU>>8; FPU is emulated
		ret

; ------------- FPU is hardware

InitFPU4:	or	byte [CPUInfo+CPU_Flags+1],CPU_FPU>>8; FPU is hardware
		fsetpm			; init protected mode on 287
		ret

; -----------------------------------------------------------------------------
;                         Initialize CPU frequency
; -----------------------------------------------------------------------------
; NOTES:	This function must be called with interrupt disabled.
; -----------------------------------------------------------------------------

; ------------- Disable output to PC speaker and enable Timer 2 output

InitCPUFreq:	in	al,61h		; get keyboard controller B
		and	al,~B1		; disable output to speaker
		or	al,B0		; enable speaker gate
		out	61h,al		; set output to speaker

; ------------- Set Timer 2 counter to 65536 (= period 54.92540 ms)

		mov	al,B7+B5+B4	; select timer 2, LSB+MSB, mode 0
		out	43h,al		; set Timer 2 mode
		xor	eax,eax		; EAX <- 0
		out	42h,al		; set divisor LOW
		SHORT_DELAY		; short delay
		out	42h,al		; set divisor HIGH

; ------------- Check if time-stamp counter is supported

		TSC_OK			; is time-stamp counter supported?
		jz	InitCPUFreq5	; time-stamp counter is not supported

; ------------- Read time-stamp counter, start time

		rdtsc			; read time-stamp counter (-> EDX:EAX)
		xchg	eax,esi		; ESI <- start time LOW
		mov	edi,edx		; EDI <- start time HIGH

; ------------- Wait for Timer 2 output

InitCPUFreq3:	in	al,61h		; read keyboard controller B
		test	al,B5		; is Timer 2 output reached?
		jz	InitCPUFreq3	; wait for end of Timer 2 counting

; ------------- Read time-stamp counter, get interval

		rdtsc			; read time-stamp counter (-> EDX:EAX)
		sub	eax,esi		; EAX <- interval LOW
		sbb	edx,edi		; EDX <- interval HIGH

; ------------- Limit counter value

		cmp	edx,byte 0fh	; maximal value
		jbe	InitCPUFreq4	; value is OK
		mov	edx,0fh		; limit maximal value HIGH
		or	eax,byte -1	; limit maximal value LOW

; ------------- Calculate frequency
		
InitCPUFreq4:	shld	edx,eax,28	; shift EDX:EAX << 28 (e.g. *2^28)
		shl	eax,28		; shift EAX << 28
		mov	ecx,14743925	; timer divisor (=0.054925401*(2^28))
		div	ecx		; calculate frequency
		jmp	short InitCPUFreq8

; ------------- Reset accumulator

InitCPUFreq5:	xor	esi,esi		; ESI <- 0, accumulator LOW
		xor	edi,edi		; EDI <- 0, accumulator HIGH

; ------------- Wait for Timer 2 output

InitCPUFreq6:   add	esi,byte 1	; increment accumulator LOW
		adc	edi,byte 0	; carry
		in	al,61h		; read keyboard controller B
		test	al,B5		; is Timer 2 output reached?
		jz	InitCPUFreq6	; wait for end of Timer 2 counting

; ------------- Limit counter value

		or	edi,edi		; maximal value
		jz	InitCPUFreq7	; value is OK
		or	esi,byte -1	; limit maximal value

; ------------- Calculate frequency
		
InitCPUFreq7:	mov	edx,esi		; EDX <- counter LOW * 2^32
		xor	eax,eax		; EAX <- 0

		mov	ecx,98300	; timer divisor for Pentium
		cmp	byte [CPUInfo+CPU_Type],CPU_PENTIUM ; Pentium?
		jae	InitCPUFreq72	; Pentium

		mov	ecx,50000	; timer divisor for 486
		cmp	byte [CPUInfo+CPU_Type],CPU_486 ; 486?
		jae	InitCPUFreq72	; 486

		mov	ecx,25000	; timer divisor for 386 DX
		cmp	byte [CPUInfo+CPU_Model],1 ; 386 DX?
		jbe	InitCPUFreq72	; 386 DX
		mov	ecx,15000	; timer divisor for 386 SX

InitCPUFreq72:	div	ecx		; calculate frequency

; ------------- Round frequency

		cmp	eax,140000000	; is it valid value?
		jae	InitCPUFreq8	; value is above valid value
		mov	esi,LowCPUFreq	; ESI <- frequency table
		mov	edi,80000000h	; EDI <- found nearest distance
InitCPUFreq74:	mov	ecx,eax		; ECX <- found frequency
		sub	ecx,[esi]	; ECX <- distance
		jns	InitCPUFreq75	; distance is not negative
		neg	ecx		; ECX <- absolute value of distance
InitCPUFreq75:	cmp	ecx,edi		; is it better frequency?
		jae	InitCPUFreq76	; it is not better frequency
		mov	ebx,eax		; EBX <- found best frequency
		mov	edi,ecx		; EDI <- distance of found best freq.
InitCPUFreq76:	add	esi,byte 4	; ESI <- next frequency
		cmp	esi,LowCPUFreq2	; end of table?
		jb	InitCPUFreq74	; next value
		xchg	eax,ebx		; EAX <- found best frequency

; ------------- Minimal value

InitCPUFreq8:	mov	ebx,2000000	; EBX <- minimal frequency (2 MHz)
		cmp	eax,ebx		; is it valid value?
		ja	InitCPUFreq9	; it is valid value
		xchg	eax,ebx		; EAX <- limit to minimal frequency
InitCPUFreq9:	mov	[CPUInfo+CPU_Frequency],eax ; store CPU frequency

; ------------- Debug display CPU info
%ifdef DEBUG_CPU
		call	DebInitCPU	; debug display CPU info
%endif
		ret

; -----------------------------------------------------------------------------
;                           Debug display CPU info
; -----------------------------------------------------------------------------
%ifdef DEBUG_CPU
; ------------- Display CPU basic type

DebInitCPU:	mov	esi,CPUMsg	; ESI <- message text
		call	DebOutText	; display text
		movzx	eax,byte [CPUInfo+CPU_Type] ; EAX <- CPU basic type
		mov	esi,[CPUMsg1_Addr+eax*4-CPU_386*4] ; ESI <- message text
		call	DebOutText	; display text

; ------------- Display CPU vendor

		mov	esi,CPUMsg2	; ESI <- message text
		call	DebOutText	; display text
		movzx	eax,byte [CPUInfo+CPU_VendorID] ; EAX <- CPU vendor
		mov	esi,[CPUMsg2_Addr+eax*4] ; ESI <- message text
		call	DebOutText	; display text

; ------------- Display CPU family

		mov	esi,CPUMsg3	; ESI <- message text
		call	DebOutText	; display text
		movzx	eax,byte [CPUInfo+CPU_Family] ; EAX <- CPU family
		call	DebOutNum	; display family

; ------------- Display CPU model

		mov	esi,CPUMsg4	; ESI <- message text
		call	DebOutText	; display text
		movzx	eax,byte [CPUInfo+CPU_Model] ; EAX <- CPU model
		call	DebOutNum	; display model

; ------------- Display CPU features

		mov	esi,CPUMsg5	; ESI <- message text
		call	DebOutText	; display text
		test	byte [CPUInfo+CPU_Flags],B1 ; MMX
		jz	DebInitCPU21	; no MMX
		mov	esi,CPUMsg5_2	; ESI <- message text
		call	DebOutText	; display text MMX
DebInitCPU21:	test	byte [CPUInfo+CPU_Flags],B2 ; SSE
		jz	DebInitCPU22	; no SSE
		mov	esi,CPUMsg5_3	; ESI <- message text
		call	DebOutText	; display text SSE
DebInitCPU22:	test	byte [CPUInfo+CPU_Flags],B3 ; SSE2
		jz	DebInitCPU23	; no SSE2
		mov	esi,CPUMsg5_4	; ESI <- message text
		call	DebOutText	; display text SSE2
DebInitCPU23:	test	byte [CPUInfo+CPU_Flags],B4 ; 3DNow!
		jz	DebInitCPU24	; no 3DNow!
		mov	esi,CPUMsg5_5	; ESI <- message text
		call	DebOutText	; display text 3DNow!
DebInitCPU24:	test	byte [CPUInfo+CPU_Flags],B5 ; 3DNow! Extended
		jz	DebInitCPU25	; no 3DNow! Extended
		mov	esi,CPUMsg5_6	; ESI <- message text
		call	DebOutText	; display text 3DNow! Extended
DebInitCPU25:	test	byte [CPUInfo+CPU_Flags],B6 ; MMX+ AMD
		jz	DebInitCPU26	; no MMX+ AMD
		mov	esi,CPUMsg5_7	; ESI <- message text
		call	DebOutText	; display text MMX+ AMD
DebInitCPU26:	test	byte [CPUInfo+CPU_Flags],B7 ; MMX+ Cyrix
		jz	DebInitCPU27	; no MMX+ Cyrix
		mov	esi,CPUMsg5_8	; ESI <- message text
		call	DebOutText	; display text MMX+ Cyrix
DebInitCPU27:	test	byte [CPUInfo+CPU_Flags+1],B8>>8 ; FPU
		jz	DebInitCPU28	; no FPU
		mov	esi,CPUMsg5_9	; ESI <- message text
		call	DebOutText	; display text FPU
DebInitCPU28:	TSC_OK			; TSC
		jz	DebInitCPU29	; no TSC
		mov	esi,CPUMsg5_10	; ESI <- message text
		call	DebOutText	; display text TSC

; ------------- Display CPU frequency

DebInitCPU29:	mov	esi,CPUMsg6	; ESI <- message text
		call	DebOutText	; display text
		mov	eax,[CPUInfo+CPU_Frequency] ; EAX <- CPU frequency
		add	eax,500		; round frequency
		xor	edx,edx		; EDX <- 0
		mov	ecx,1000	; ECX <- divider
		div	ecx		; EAX <- frequency in kHz
		call	DebOutNum	; display CPU frequency
                mov	esi,CPUMsg7	; ESI <- message text
		call	DebOutText	; display text
		ret
%endif
; -----------------------------------------------------------------------------
;                                   Data
; -----------------------------------------------------------------------------

		DATA_SECTION

; ------------- Vendor strings

CPUVendString:	db	'GenuineIntel'	; Intel
		db	'AuthenticAMD'	; AMD
		db	'CyrixInstead'	; Cyrix
		db	'CentaurHauls'	; Centaur
		db	'NexGenDriven'	; NexGen
		db	'GenuineTMx86'	; Transmeta
		db	'RiseRiseRise'	; Rise
		db	'UMC UMC UMC '	; UMC
		db	'SiS SiS SiS '	; SiS
		db	'Geode by NSC'	; National Semiconductor

; ------------- Low-CPU typical frequencies

LowCPUFreq:	dd	16666667	; 16 MHz
		dd	20000000	; 20 MHz
		dd	25000000	; 25 MHz
		dd	33333333	; 33 MHz
		dd	40000000	; 40 MHz
		dd	50000000	; 50 MHz
		dd	60000000	; 60 MHz
		dd	66666667	; 66 MHz
		dd	75000000	; 75 MHz
		dd	80000000	; 80 MHz
		dd	100000000	; 100 MHz
		dd	120000000	; 120 MHz
		dd	133333333	; 133 MHz
LowCPUFreq2:

; ------------- Debug messages
%ifdef DEBUG_CPU
CPUMsg:		db	10,'--- CPU:',10
		db	'Basic type: ',0
CPUMsg1_386:	db	'386',0
CPUMsg1_486:	db	'486',0
CPUMsg1_P1:	db	'Pentium',0
CPUMsg1_P2:	db	'Pentium 2, Pentium Pro',0
CPUMsg1_P3:	db	'Pentium 3',0
CPUMsg1_P4:	db	'Pentium 4',0

CPUMsg1_Addr:	dd	CPUMsg1_386
		dd	CPUMsg1_486
		dd	CPUMsg1_P1
		dd	CPUMsg1_P2
		dd	CPUMsg1_P3
		dd	CPUMsg1_P4

CPUMsg2:	db	10,'Vendor: ',0
CPUMsg2_0:	db	'unknown',0
CPUMsg2_1:	db	'Intel',0
CPUMsg2_2:	db	'AMD',0
CPUMsg2_3:	db	'Cyrix',0
CPUMsg2_4:	db	'Centaur',0
CPUMsg2_5:	db	'NexGen',0
CPUMsg2_6:	db	'Transmeta',0
CPUMsg2_7:	db	'Rise',0
CPUMsg2_8:	db	'UMC',0
CPUMsg2_9:	db	'SiS',0
CPUMsg2_10:	db	'National Semiconductor',0

CPUMsg2_Addr:	dd	CPUMsg2_0
		dd	CPUMsg2_1
		dd	CPUMsg2_2
		dd	CPUMsg2_3
		dd	CPUMsg2_4
		dd	CPUMsg2_5
		dd	CPUMsg2_6
		dd	CPUMsg2_7
		dd	CPUMsg2_8
		dd	CPUMsg2_9
		dd	CPUMsg2_10

CPUMsg3:	db	10,'Family: ',0

CPUMsg4:	db	10,'Model: ',0

CPUMsg5:	db	10,'Features: ',0
CPUMsg5_2:	db	'MMX ',0
CPUMsg5_3:	db	'SSE ',0
CPUMsg5_4:	db	'SSE2 ',0
CPUMsg5_5:	db	'3DNow! ',0
CPUMsg5_6:	db	'3DNow!ext ',0
CPUMsg5_7:	db	'MMX+(AMD) ',0
CPUMsg5_8:	db	'MMX+(Cyrix) ',0
CPUMsg5_9:	db	'FPU ',0
CPUMsg5_10:	db	'TSC ',0

CPUMsg6:	db	10,'Frequency: ',0
CPUMsg7:	db	' kHz',10,0
%endif
; -----------------------------------------------------------------------------
;                            Uninitialized data
; -----------------------------------------------------------------------------

		BSS_SECTION

; ------------- CPU information

		align	8, resb 1
CPUInfo:	resb	CPUINFO_size

Back to source browser