;
; $Log: x86tcssp.asm,v $
; Revision 1.2  1998/09/07 21:21:21  jlawson
; fixed line breaks
;
; Revision 1.1  1998/06/26 08:39:23  cyruspatel
; Modified netware.cpp to use new GetTimesliceBaseline() function. Added
; netware.h to repository.
;
;

;
; Detect CPU speed. Warning! not for use in v86 mode (does not check!)
; Returns s32  >0   processor speed in MHz
;              -1   hardware doesn't support P5 type timecode stamping
; Written June 23, 1998 Cyrus Patel <cyp@fb14.uni-mainz.de>
;

.386p
.387

ifndef __SMALL__
  .model flat
endif

                EXTRN GetCurrentTime:near
ReadTickerLow   macro 
                ;NetWare            
                call GetCurrentTime 

                ;DOS/Win16/Win32 (not WinNT!)            
                ;xor  eax, eax
                ;out  070h, al
                ;xor  ax, ax  
                ;in   al, 071h  ; only care about lsb anyway
                
                ;;DOS only (also in pmode)
                ;push  es
                ;mov   ax,40h
                ;mov   es,ax
                ;mov   eax,dword ptr es:[006Ch]
                ;pop   es
endm            

                PUBLIC  _x86cpuspeedtcs
                PUBLIC  x86cpuspeedtcs      ; watcom asm prepends an extra '_'

_TEXT           SEGMENT DWORD PUBLIC USE32 'CODE'
                ;ASSUME CS:_TEXT, DS:DGROUP

x86cpuspeedtcs:
_x86cpuspeedtcs:call    get_cpuspeed
                or      eax,eax
                jnz     x86cpuspeed_end
                dec     eax
x86cpuspeed_end:ret

is_cpuid_supported:
                pushfd                  ; preserve current flags
                push    ecx             ; preserve ecx
                pushfd                  ; get extended flags
                pop     eax             ; ...into eax
                mov     ecx, eax        ; save current flags
                xor     eax, 200000h    ; toggle bit 21
                push    eax             ; copy modified flagbits 
                popfd                   ; ...into flags 
                pushfd                  ; get extended flags
                pop     eax             ; ...into eax
                xor     eax, ecx        ; if bit 21 changeable then eax <> 0
                pop     ecx             ; restore preserved ecx
                popfd                   ; restore preserved flags
                cmp     eax,1           ; set carry if zero (ie no cpuid)
                cmc                     ; set carry if !zero (ie has cpuid)
                sbb     eax,eax         ; make eax==-1 if has cpuid, else 0
                and     eax,1           ; make eax==1 if has cpuid, else 0
                ret
                
_rdtsc_ macro 
       db 0fh, 031h
endm
_cpuid_ macro 
       db 0fh, 0a2h
endm

get_cpuid_maxlevel:
                call    is_cpuid_supported
                or      eax, eax
                mov     eax, -1
                jz      get_cpuid_maxlevel_end
                push    ebx
                push    ecx
                push    edx
                inc     eax
                _cpuid_
                pop     edx
                pop     ecx
                pop     ebx
get_cpuid_maxlevel_end:
                ret        
                
is_tsc_supported:
                call    get_cpuid_maxlevel        
                cmp     eax,1
                mov     eax,0
                jl      is_tsc_supported_end
                inc     eax
                push    ebx
                push    ecx
                push    edx
                _cpuid_ 
                mov     eax,edx
                pop     edx
                pop     ecx
                pop     ebx
                and     eax,10h
                shr     al,4
is_tsc_supported_end:        
                ret

     
read_tsc_per_tick:      
                call    is_tsc_supported
                or      eax,eax
                jz      rdtsc_per_tick_end
                push    ebx
rdtsc_per_tick1:pushf                   
                sti
                ReadTickerLow        ; timerticks
                mov     ebx, eax
rdtsc_per_tick2:ReadTickerLow  
                cmp     ebx, eax
                jz      rdtsc_per_tick2
                mov     ebx, eax
rdtsc_per_tick3:ReadTickerLow  
                cmp     ebx, eax
                jz      rdtsc_per_tick3
                mov     ebx, eax
                _rdtsc_
                mov     ecx, eax
rdtsc_per_tick4:ReadTickerLow  
                cmp     ebx, eax
                jz      rdtsc_per_tick4
                _rdtsc_
                popf
                sub     eax, ecx
                jb      rdtsc_per_tick1
                pop     ebx
rdtsc_per_tick_end:
                ret
                
get_cpuspeed:   call    read_tsc_per_tick
                or      eax,eax
                jz      get_cpuspeed_end
                xor     edx, edx
                mov     ecx, 18206
                mul     ecx
                add     eax, 500000000
                adc     edx, 0
                mov     ecx, 1000000000
                div     ecx
                mov     ecx, eax
                xor     eax, eax
                mov     ax, cx
get_cpuspeed_end:ret



;start:          call  get_cpuspeed
;                mov   ecx,10
;                xor   dx,dx
;                div   cx 
;                add   dl,'0'
;                mov   bl,dl
;                xor   dx,dx
;                div   cx
;                add   dl,'0'
;                mov   bh,dl
;                xor   dx,dx
;                div   cx
;                add   dl,'0'
;                mov   ah,2
;                int   21h
;                mov   dl,bh
;                mov   ah,2
;                int   21h
;                mov   dl,bl
;                mov   ah,2
;                int   21h
;                mov   ah,4ch
;                int   21h

_TEXT            ends
                 END

