1 ;****************************************************************************
3 ;* SciTech Nucleus Graphics Architecture
5 ;* Copyright (C) 1991-1998 SciTech Software, Inc.
6 ;* All rights reserved.
8 ;* ======================================================================
9 ;* |REMOVAL OR MODIFICATION OF THIS HEADER IS STRICTLY PROHIBITED BY LAW|
11 ;* |This copyrighted computer code contains proprietary technology |
12 ;* |owned by SciTech Software, Inc., located at 505 Wall Street, |
13 ;* |Chico, CA 95928 USA (http://www.scitechsoft.com). |
15 ;* |The contents of this file are subject to the SciTech Nucleus |
16 ;* |License; you may *not* use this file or related software except in |
17 ;* |compliance with the License. You may obtain a copy of the License |
18 ;* |at http://www.scitechsoft.com/nucleus-license.txt |
20 ;* |Software distributed under the License is distributed on an |
21 ;* |"AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or |
22 ;* |implied. See the License for the specific language governing |
23 ;* |rights and limitations under the License. |
25 ;* |REMOVAL OR MODIFICATION OF THIS HEADER IS STRICTLY PROHIBITED BY LAW|
26 ;* ======================================================================
28 ;* Language: 80386 Assembler, NASM or TASM
29 ;* Environment: IBM PC 32 bit Protected Mode.
31 ;* Description: Assembly support functions for the Nucleus library for
32 ;* the high resolution timing support functions provided by
33 ;* the Intel Pentium and compatible processors.
35 ;****************************************************************************
39 include "scitech.mac" ; Memory model macros
65 ;----------------------------------------------------------------------------
66 ; bool _GA_haveCPUID(void)
67 ;----------------------------------------------------------------------------
68 ; Determines if we have support for the CPUID instruction.
69 ;----------------------------------------------------------------------------
70 cprocstart _GA_haveCPUID
73 pushfd ; Get original EFLAGS
76 xor eax, 200000h ; Flip ID bit in EFLAGS
77 push eax ; Save new EFLAGS value on stack
78 popfd ; Replace current EFLAGS value
79 pushfd ; Get new EFLAGS
80 pop eax ; Store new EFLAGS in EAX
81 xor eax, ecx ; Can not toggle ID bit,
82 jnz @@1 ; Processor=80486
83 mov eax,0 ; We dont have CPUID support
85 @@1: mov eax,1 ; We have CPUID support
91 ;----------------------------------------------------------------------------
92 ; uint _GA_getCPUIDFeatures(void)
93 ;----------------------------------------------------------------------------
94 ; Determines the CPU type using the CPUID instruction.
95 ;----------------------------------------------------------------------------
96 cprocstart _GA_getCPUIDFeatures
100 xor eax, eax ; Set up for CPUID instruction
101 mCPU_ID ; Get and save vendor ID
102 cmp eax, 1 ; Make sure 1 is valid input for CPUID
103 jl @@Fail ; We dont have the CPUID instruction
106 mCPU_ID ; Get family/model/stepping/features
116 ;----------------------------------------------------------------------------
117 ; void _GA_readTimeStamp(GA_largeInteger *time)
118 ;----------------------------------------------------------------------------
119 ; Reads the time stamp counter and returns the 64-bit result.
120 ;----------------------------------------------------------------------------
121 cprocstart _GA_readTimeStamp
124 mov ecx,[esp+4] ; Access directly without stack frame
131 ;----------------------------------------------------------------------------
132 ; N_uint32 GA_TimerDifference(GA_largeInteger *a,GA_largeInteger *b)
133 ;----------------------------------------------------------------------------
134 ; Computes the difference between two 64-bit numbers (a-b)
135 ;----------------------------------------------------------------------------
136 cprocstart GA_TimerDifference
138 ARG a:DPTR, b:DPTR, t:DPTR
143 mov eax,[ecx] ; EAX := b.low
146 mov edx,eax ; EDX := low difference
148 mov eax,[ecx+4] ; ECX := b.high
150 sbb eax,[ecx+4] ; EAX := high difference
151 mov eax,edx ; Return low part
158 ; Macro to delay briefly to ensure that enough time has elapsed between
159 ; successive I/O accesses so that the device being accessed can respond
160 ; to both accesses even on a very fast PC.
176 ;----------------------------------------------------------------------------
177 ; void _OS_delay8253(N_uint32 microSeconds);
178 ;----------------------------------------------------------------------------
179 ; Delays for the specified number of microseconds, by directly programming
180 ; the 8253 timer chips.
181 ;----------------------------------------------------------------------------
182 cprocstart _OS_delay8253
188 ; Start timer 2 counting
190 mov _ax,[microSec] ; EAX := count in microseconds
195 mov ecx,eax ; ECX := count in timer ticks
200 ; Set the timer 2 count to 0 again to start the timing interval.
202 mov al,10110100b ; set up to load initial (timer 2)
203 out 43h,al ; timer count
206 out 42h,al ; load count lsb
208 out 42h,al ; load count msb
209 xor di,di ; Allow max 64K loop iterations
212 dec di ; This is a guard against the possibility that
213 jz @@LoopEnd ; someone eg. stopped the timer behind our back.
214 ; After 64K iterations we bail out no matter what
215 ; (and hope it wasn't too soon)
216 mov al,00000000b ; latch timer 0
219 in al,42h ; least significant byte
222 in al,42h ; most significant byte
224 neg ax ; Convert from countdown remaining
226 cmp ax,cx ; Has delay expired?
227 jb @@LoopStart ; No, so loop till done
229 ; Stop timer 2 from counting
235 ; Some programs have a problem if we change the control port; better change it
236 ; to something they expect (mode 3 - square wave generator)...