summaryrefslogtreecommitdiffstats
path: root/board/MAI/bios_emulator/scitech/src/pm/common/_cpuinfo.asm
diff options
context:
space:
mode:
Diffstat (limited to 'board/MAI/bios_emulator/scitech/src/pm/common/_cpuinfo.asm')
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/common/_cpuinfo.asm600
1 files changed, 600 insertions, 0 deletions
diff --git a/board/MAI/bios_emulator/scitech/src/pm/common/_cpuinfo.asm b/board/MAI/bios_emulator/scitech/src/pm/common/_cpuinfo.asm
new file mode 100644
index 0000000000..60ebed713f
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/common/_cpuinfo.asm
@@ -0,0 +1,600 @@
+;****************************************************************************
+;*
+;* 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.
+;*
+;****************************************************************************
+
+ IDEAL
+
+include "scitech.mac"
+
+header _cpuinfo
+
+begdataseg _cpuinfo ; Start of data segment
+
+cache_id db "01234567890123456"
+intel_id db "GenuineIntel" ; Intel vendor ID
+cyrix_id db "CyrixInstead" ; Cyrix vendor ID
+amd_id db "AuthenticAMD" ; AMD vendor ID
+idt_id db "CentaurHauls" ; IDT vendor ID
+
+CPU_IDT EQU 01000h ; Flag for IDT processors
+CPU_Cyrix EQU 02000h ; Flag for Cyrix processors
+CPU_AMD EQU 04000h ; Flag for AMD processors
+CPU_Intel EQU 08000h ; Flag for Intel processors
+
+enddataseg _cpuinfo
+
+begcodeseg _cpuinfo ; Start of code segment
+
+ifdef USE_NASM
+%macro mCPU_ID 0
+db 00Fh,0A2h
+%endmacro
+else
+MACRO mCPU_ID
+db 00Fh,0A2h
+ENDM
+endif
+
+ifdef USE_NASM
+%macro mRDTSC 0
+db 00Fh,031h
+%endmacro
+else
+MACRO mRDTSC
+db 00Fh,031h
+ENDM
+endif
+
+;----------------------------------------------------------------------------
+; 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, sp
+ifdef USE_NASM
+ and sp, ~3
+else
+ and sp, not 3
+endif
+ 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
+ ret
+
+cprocend
+
+;----------------------------------------------------------------------------
+; 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
+ ret
+
+cprocend
+
+;----------------------------------------------------------------------------
+; 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
+ ret
+
+cprocend
+
+;----------------------------------------------------------------------------
+; bool _CPU_haveCPUID(void)
+;----------------------------------------------------------------------------
+; Determines if we have support for the CPUID instruction.
+;----------------------------------------------------------------------------
+cprocstart _CPU_haveCPUID
+
+ enter_c
+
+ifdef 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 support
+else
+ mov eax,0 ; CPUID requires 32-bit pmode
+endif
+@@Done: leave_c
+ ret
+
+cprocend
+
+;----------------------------------------------------------------------------
+; 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
+
+ LEA_L esi,intel_id
+ cmp [DWORD esi], ebx
+ jne @@NotIntel
+ cmp [DWORD esi+4], edx
+ jne @@NotIntel
+ cmp [DWORD esi+8], ecx
+ jne @@NotIntel
+ mov eax,CPU_Intel ; Flag that we have GenuineIntel
+ jmp @@FoundVendor
+
+; Check for CyrixInstead processors
+
+@@NotIntel:
+ LEA_L esi,cyrix_id
+ cmp [DWORD esi], ebx
+ jne @@NotCyrix
+ cmp [DWORD esi+4], edx
+ jne @@NotCyrix
+ cmp [DWORD esi+8], ecx
+ jne @@NotCyrix
+ mov eax,CPU_Cyrix ; Flag that we have CyrixInstead
+ jmp @@FoundVendor
+
+; Check for AuthenticAMD processors
+
+@@NotCyrix:
+ LEA_L esi,amd_id
+ cmp [DWORD esi], ebx
+ jne @@NotAMD
+ cmp [DWORD esi+4], edx
+ jne @@NotAMD
+ cmp [DWORD esi+8], ecx
+ jne @@NotAMD
+ mov eax,CPU_AMD ; Flag that we have AuthenticAMD
+ jmp @@FoundVendor
+
+; Check for CentaurHauls processors
+
+@@NotAMD:
+ LEA_L esi,idt_id
+ cmp [DWORD esi], ebx
+ jne @@NotIDT
+ cmp [DWORD esi+4], edx
+ jne @@NotIDT
+ cmp [DWORD esi+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 @@Done
+
+cprocend
+
+;----------------------------------------------------------------------------
+; 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 @@Done
+
+cprocend
+
+;----------------------------------------------------------------------------
+; uint _CPU_getCPUIDStepping(void)
+;----------------------------------------------------------------------------
+; Determines the CPU type using the CPUID instruction.
+;----------------------------------------------------------------------------
+cprocstart _CPU_getCPUIDStepping
+
+ 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, 00Fh ; Isolate stepping
+@@Done: leave_c
+ ret
+
+@@Fail: xor eax,eax
+ jmp @@Done
+
+cprocend
+
+;----------------------------------------------------------------------------
+; 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 @@Done
+
+cprocend
+
+;----------------------------------------------------------------------------
+; uint _CPU_getCacheSize(void)
+;----------------------------------------------------------------------------
+; Determines the CPU cache size for Intel processors
+;----------------------------------------------------------------------------
+cprocstart _CPU_getCacheSize
+
+ enter_c
+ xor eax, eax ; Set up for CPUID instruction
+ mCPU_ID ; Get and save vendor ID
+ cmp eax,2 ; Make sure 2 is valid input for CPUID
+ jl @@Fail ; We dont have the CPUID instruction
+ mov eax,2
+ mCPU_ID ; Get cache descriptors
+ LEA_L esi,cache_id ; Get address of cache ID (-fPIC aware)
+ shr eax,8
+ mov [esi+0],eax
+ mov [esi+3],ebx
+ mov [esi+7],ecx
+ mov [esi+11],edx
+ xor eax,eax
+ LEA_L esi,cache_id ; Get address of cache ID (-fPIC aware)
+ mov edi,15
+@@ScanLoop:
+ cmp [BYTE esi],41h
+ mov eax,128
+ je @@Done
+ cmp [BYTE esi],42h
+ mov eax,256
+ je @@Done
+ cmp [BYTE esi],43h
+ mov eax,512
+ je @@Done
+ cmp [BYTE esi],44h
+ mov eax,1024
+ je @@Done
+ cmp [BYTE esi],45h
+ mov eax,2048
+ je @@Done
+ inc esi
+ dec edi
+ jnz @@ScanLoop
+
+@@Done: leave_c
+ ret
+
+@@Fail: xor eax,eax
+ jmp @@Done
+
+cprocend
+
+;----------------------------------------------------------------------------
+; 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 @@Done
+
+cprocend
+
+;----------------------------------------------------------------------------
+; ulong _CPU_quickRDTSC(void)
+;----------------------------------------------------------------------------
+; Reads the time stamp counter and returns the low order 32-bits
+;----------------------------------------------------------------------------
+cprocstart _CPU_quickRDTSC
+
+ mRDTSC
+ ret
+
+cprocend
+
+;----------------------------------------------------------------------------
+; 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
+ ret
+
+cprocend
+
+;----------------------------------------------------------------------------
+; 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
+ ret
+
+cprocend
+
+;----------------------------------------------------------------------------
+; 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 part
+ifndef flatmodel
+ shld edx,eax,16 ; Return in DX:AX
+endif
+ leave_c
+ ret
+
+cprocend
+
+;----------------------------------------------------------------------------
+; 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) / 0x100000
+ifndef flatmodel
+ shld edx,eax,16 ; Return in DX:AX
+endif
+ leave_c
+ ret
+
+cprocend
+
+;----------------------------------------------------------------------------
+; ulong _CPU_mulDiv(ulong a,ulong b,ulong c);
+;----------------------------------------------------------------------------
+; Computes the following with 64-bit integer precision:
+;
+; result = (a * b) / c
+;
+;----------------------------------------------------------------------------
+cprocstart _CPU_mulDiv
+
+ ARG a:ULONG, b:ULONG, c:ULONG
+
+ enter_c
+ mov eax,[a]
+ imul [ULONG b]
+ idiv [ULONG c]
+ifndef flatmodel
+ shld edx,eax,16 ; Return in DX:AX
+endif
+ leave_c
+ ret
+
+cprocend
+
+endcodeseg _cpuinfo
+
+ END
OpenPOWER on IntegriCloud