📄 _cpuinfo.asm
字号:
;****************************************************************************;*;* SciTech OS Portability Manager Library;*;* ========================================================================;*;* The contents of this file are subject to the SciTech MGL Public;* License Version 1.0 (the "License"); you may not use this file;* except in compliance with the License. You may obtain a copy of;* the License at http://www.scitechsoft.com/mgl-license.txt;*;* Software distributed under the License is distributed on an;* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or;* implied. See the License for the specific language governing;* rights and limitations under the License.;*;* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.;*;* The Initial Developer of the Original Code is SciTech Software, Inc.;* All Rights Reserved.;*;* ========================================================================;*;* Language: NASM or TASM Assembler;* Environment: Intel 32 bit Protected Mode.;*;* Description: Code to determine the Intel processor type.;*;**************************************************************************** IDEALinclude "scitech.mac"header _cpuinfobegcodeseg _cpuinfo ; Start of code segmentifdef USE_NASM%macro mCPU_ID 0db 00Fh,0A2h%endmacroelseMACRO mCPU_IDdb 00Fh,0A2hENDMendififdef USE_NASM%macro mRDTSC 0db 00Fh,031h%endmacroelseMACRO mRDTSCdb 00Fh,031hENDMendifCPU_IDT EQU 01000h ; Flag for IDT processorsCPU_Cyrix EQU 02000h ; Flag for Cyrix processorsCPU_AMD EQU 04000h ; Flag for AMD processorsCPU_Intel EQU 08000h ; Flag for Intel processorsintel_id db "GenuineIntel" ; Intel vendor IDcyrix_id db "CyrixInstead" ; Cyrix vendor IDamd_id db "AuthenticAMD" ; AMD vendor IDidt_id db "CentaurHauls" ; IDT vendor ID;----------------------------------------------------------------------------; bool _CPU_check80386(void);----------------------------------------------------------------------------; Determines if we have an i386 processor.;----------------------------------------------------------------------------cprocstart _CPU_check80386 enter_c xor edx,edx ; EDX = 0, not an 80386 mov bx, spifdef USE_NASM and sp, ~3else and sp, not 3endif pushfd ; Push original EFLAGS pop eax ; Get original EFLAGS mov ecx, eax ; Save original EFLAGS xor eax, 40000h ; Flip AC bit in EFLAGS push eax ; Save new EFLAGS value on ; stack popfd ; Replace current EFLAGS value pushfd ; Get new EFLAGS pop eax ; Store new EFLAGS in EAX xor eax, ecx ; Can't toggle AC bit, ; processor=80386 jnz @@Done ; Jump if not an 80386 processor inc edx ; We have an 80386@@Done: push ecx popfd mov sp, bx mov eax, edx leave_c retcprocend;----------------------------------------------------------------------------; bool _CPU_check80486(void);----------------------------------------------------------------------------; Determines if we have an i486 processor.;----------------------------------------------------------------------------cprocstart _CPU_check80486 enter_c; Distinguish between the i486 and Pentium by the ability to set the ID flag; in the EFLAGS register. If the ID flag is set, then we can use the CPUID; instruction to determine the final version of the chip. Otherwise we; simply have an 80486.; Distinguish between the i486 and Pentium by the ability to set the ID flag; in the EFLAGS register. If the ID flag is set, then we can use the CPUID; instruction to determine the final version of the chip. Otherwise we; simply have an 80486. pushfd ; Get original EFLAGS pop eax mov ecx, eax xor eax, 200000h ; Flip ID bit in EFLAGS push eax ; Save new EFLAGS value on stack popfd ; Replace current EFLAGS value pushfd ; Get new EFLAGS pop eax ; Store new EFLAGS in EAX xor eax, ecx ; Can not toggle ID bit, jnz @@1 ; Processor=80486 mov eax,1 ; We dont have a Pentium jmp @@Done@@1: mov eax,0 ; We have Pentium or later@@Done: leave_c retcprocend;----------------------------------------------------------------------------; bool _CPU_checkClone(void);----------------------------------------------------------------------------; Checks if the i386 or i486 processor is a clone or genuine Intel.;----------------------------------------------------------------------------cprocstart _CPU_checkClone enter_c mov ax,5555h ; Check to make sure this is a 32-bit processor xor dx,dx mov cx,2h div cx ; Perform Division clc jnz @@NoClone jmp @@Clone@@NoClone: stc@@Clone: pushfd pop eax ; Get the flags and eax,1 xor eax,1 ; EAX=0 is probably Intel, EAX=1 is a Clone leave_c retcprocend;----------------------------------------------------------------------------; bool _CPU_haveCPUID(void);----------------------------------------------------------------------------; Determines if we have support for the CPUID instruction.;----------------------------------------------------------------------------cprocstart _CPU_haveCPUID enter_cifdef flatmodel pushfd ; Get original EFLAGS pop eax mov ecx, eax xor eax, 200000h ; Flip ID bit in EFLAGS push eax ; Save new EFLAGS value on stack popfd ; Replace current EFLAGS value pushfd ; Get new EFLAGS pop eax ; Store new EFLAGS in EAX xor eax, ecx ; Can not toggle ID bit, jnz @@1 ; Processor=80486 mov eax,0 ; We dont have CPUID support jmp @@Done@@1: mov eax,1 ; We have CPUID supportelse mov eax,0 ; CPUID requires 32-bit pmodeendif@@Done: leave_c retcprocend;----------------------------------------------------------------------------; uint _CPU_checkCPUID(void);----------------------------------------------------------------------------; Determines the CPU type using the CPUID instruction.;----------------------------------------------------------------------------cprocstart _CPU_checkCPUID enter_c xor eax, eax ; Set up for CPUID instruction mCPU_ID ; Get and save vendor ID cmp eax, 1 ; Make sure 1 is valid input for CPUID jl @@Fail ; We dont have the CPUID instruction xor eax,eax ; Assume vendor is unknown; Check for GenuineIntel processors cmp [DWORD intel_id], ebx jne @@NotIntel cmp [DWORD intel_id+4], edx jne @@NotIntel cmp [DWORD intel_id+8], ecx jne @@NotIntel mov eax,CPU_Intel ; Flag that we have GenuineIntel jmp @@FoundVendor; Check for CyrixInstead processors@@NotIntel: cmp [DWORD cyrix_id], ebx jne @@NotCyrix cmp [DWORD cyrix_id+4], edx jne @@NotCyrix cmp [DWORD cyrix_id+8], ecx jne @@NotCyrix mov eax,CPU_Cyrix ; Flag that we have CyrixInstead jmp @@FoundVendor; Check for AuthenticAMD processors@@NotCyrix: cmp [DWORD amd_id], ebx jne @@NotAMD cmp [DWORD amd_id+4], edx jne @@NotAMD cmp [DWORD amd_id+8], ecx jne @@NotAMD mov eax,CPU_AMD ; Flag that we have AuthenticAMD jmp @@FoundVendor; Check for CentaurHauls processors@@NotAMD: cmp [DWORD idt_id], ebx jne @@NotIDT cmp [DWORD idt_id+4], edx jne @@NotIDT cmp [DWORD idt_id+8], ecx jne @@NotIDT mov eax,CPU_IDT ; Flag that we have AuthenticIDT jmp @@FoundVendor@@NotIDT:@@FoundVendor: push eax xor eax, eax inc eax mCPU_ID ; Get family/model/stepping/features and eax, 0F00h shr eax, 8 ; Isolate family and eax, 0Fh pop ecx or eax,ecx ; Combine in the clone flag@@Done: leave_c ret@@Fail: xor eax,eax jmp @@Donecprocend;----------------------------------------------------------------------------; uint _CPU_getCPUIDModel(void);----------------------------------------------------------------------------; Determines the CPU type using the CPUID instruction.;----------------------------------------------------------------------------cprocstart _CPU_getCPUIDModel enter_c xor eax, eax ; Set up for CPUID instruction mCPU_ID ; Get and save vendor ID cmp eax, 1 ; Make sure 1 is valid input for CPUID jl @@Fail ; We dont have the CPUID instruction xor eax, eax inc eax mCPU_ID ; Get family/model/stepping/features and eax, 0F0h shr eax, 4 ; Isolate model@@Done: leave_c ret@@Fail: xor eax,eax jmp @@Donecprocend;----------------------------------------------------------------------------; uint _CPU_getCPUIDFeatures(void);----------------------------------------------------------------------------; Determines the CPU type using the CPUID instruction.;----------------------------------------------------------------------------cprocstart _CPU_getCPUIDFeatures enter_c xor eax, eax ; Set up for CPUID instruction mCPU_ID ; Get and save vendor ID cmp eax, 1 ; Make sure 1 is valid input for CPUID jl @@Fail ; We dont have the CPUID instruction xor eax, eax inc eax mCPU_ID ; Get family/model/stepping/features mov eax, edx@@Done: leave_c ret@@Fail: xor eax,eax jmp @@Donecprocend;----------------------------------------------------------------------------; uint _CPU_have3DNow(void);----------------------------------------------------------------------------; Determines the CPU type using the CPUID instruction.;----------------------------------------------------------------------------cprocstart _CPU_have3DNow enter_c mov eax,80000000h ; Query for extended functions mCPU_ID ; Get extended function limit cmp eax,80000001h jbe @@Fail ; Nope, we dont have function 800000001h mov eax,80000001h ; Setup extended function 800000001h mCPU_ID ; and get the information test edx,80000000h ; Bit 31 is set if 3DNow! present jz @@Fail ; Nope, we dont have 3DNow support mov eax,1 ; Yep, we have 3DNow! support!@@Done: leave_c ret@@Fail: xor eax,eax jmp @@Donecprocend;----------------------------------------------------------------------------; ulong _CPU_quickRDTSC(void);----------------------------------------------------------------------------; Reads the time stamp counter and returns the low order 32-bits;----------------------------------------------------------------------------cprocstart _CPU_quickRDTSC mRDTSC retcprocend;----------------------------------------------------------------------------; void _CPU_runBSFLoop(ulong interations);----------------------------------------------------------------------------; Runs a loop of BSF instructions for the specified number of iterations;----------------------------------------------------------------------------cprocstart _CPU_runBSFLoop ARG iterations:ULONG push _bp mov _bp,_sp push _bx mov edx,[iterations] mov eax,80000000h mov ebx,edx ALIGN 4@@loop: bsf ecx,eax dec ebx jnz @@loop pop _bx pop _bp retcprocend;----------------------------------------------------------------------------; void _CPU_readTimeStamp(CPU_largeInteger *time);;----------------------------------------------------------------------------; Reads the time stamp counter and returns the 64-bit result.;----------------------------------------------------------------------------cprocstart _CPU_readTimeStamp mRDTSC mov ecx,[esp+4] ; Access directly without stack frame mov [ecx],eax mov [ecx+4],edx retcprocend;----------------------------------------------------------------------------; ulong _CPU_diffTime64(CPU_largeInteger *t1,CPU_largeInteger *t2,CPU_largeInteger *t);----------------------------------------------------------------------------; Computes the difference between two 64-bit numbers.;----------------------------------------------------------------------------cprocstart _CPU_diffTime64 ARG t1:DPTR, t2:DPTR, t:DPTR enter_c mov ecx,[t2] mov eax,[ecx] ; EAX := t2.low mov ecx,[t1] sub eax,[ecx] mov edx,eax ; EDX := low difference mov ecx,[t2] mov eax,[ecx+4] ; ECX := t2.high mov ecx,[t1] sbb eax,[ecx+4] ; EAX := high difference mov ebx,[t] ; Store the result mov [ebx],edx ; Store low part mov [ebx+4],eax ; Store high part mov eax,edx ; Return low partifndef flatmodel shld edx,eax,16 ; Return in DX:AXendif leave_c retcprocend;----------------------------------------------------------------------------; ulong _CPU_calcMicroSec(CPU_largeInteger *count,ulong freq);;----------------------------------------------------------------------------; Computes the value in microseconds for the elapsed time with maximum; precision. The formula we use is:;; us = (((diff * 0x100000) / freq) * 1000000) / 0x100000);; The power of two multiple before the first divide allows us to scale the; 64-bit difference using simple shifts, and then the divide brings the; final result into the range to fit into a 32-bit integer.;----------------------------------------------------------------------------cprocstart _CPU_calcMicroSec ARG count:DPTR, freq:ULONG enter_c mov ecx,[count] mov eax,[ecx] ; EAX := low part mov edx,[ecx+4] ; EDX := high part shld edx,eax,20 shl eax,20 ; diff * 0x100000 div [DWORD freq] ; (diff * 0x100000) / freq mov ecx,1000000 xor edx,edx mul ecx ; ((diff * 0x100000) / freq) * 1000000) shrd eax,edx,20 ; ((diff * 0x100000) / freq) * 1000000) / 0x100000ifndef flatmodel shld edx,eax,16 ; Return in DX:AXendif leave_c retcprocend;----------------------------------------------------------------------------; int _CPU_inp(int port);----------------------------------------------------------------------------; Reads a byte from the specified port;----------------------------------------------------------------------------cprocstart _CPU_inp ARG port:UINT push _bp mov _bp,_sp xor _ax,_ax mov _dx,[port] in al,dx pop _bp retcprocend;----------------------------------------------------------------------------; void _CPU_outp(int port,int value);----------------------------------------------------------------------------; Write a byte to the specified port.;----------------------------------------------------------------------------cprocstart _CPU_outp ARG port:UINT, value:UINT push _bp mov _bp,_sp mov _dx,[port] mov _ax,[value] out dx,al pop _bp retcprocendendcodeseg _cpuinfo END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -