]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/MAI/bios_emulator/scitech/src/pm/common/_cpuinfo.asm
* Patch by Thomas Frieden, 13 Nov 2002:
[karo-tx-uboot.git] / board / MAI / bios_emulator / scitech / src / pm / common / _cpuinfo.asm
1 ;****************************************************************************
2 ;*
3 ;*                  SciTech OS Portability Manager Library
4 ;*
5 ;*  ========================================================================
6 ;*
7 ;*    The contents of this file are subject to the SciTech MGL Public
8 ;*    License Version 1.0 (the "License"); you may not use this file
9 ;*    except in compliance with the License. You may obtain a copy of
10 ;*    the License at http://www.scitechsoft.com/mgl-license.txt
11 ;*
12 ;*    Software distributed under the License is distributed on an
13 ;*    "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 ;*    implied. See the License for the specific language governing
15 ;*    rights and limitations under the License.
16 ;*
17 ;*    The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
18 ;*
19 ;*    The Initial Developer of the Original Code is SciTech Software, Inc.
20 ;*    All Rights Reserved.
21 ;*
22 ;*  ========================================================================
23 ;*
24 ;* Language:    NASM or TASM Assembler
25 ;* Environment: Intel 32 bit Protected Mode.
26 ;*
27 ;* Description: Code to determine the Intel processor type.
28 ;*
29 ;****************************************************************************
30
31         IDEAL
32
33 include "scitech.mac"
34
35 header      _cpuinfo
36
37 begdataseg  _cpuinfo                ; Start of data segment
38
39 cache_id    db  "01234567890123456"
40 intel_id    db  "GenuineIntel"      ; Intel vendor ID
41 cyrix_id    db  "CyrixInstead"      ; Cyrix vendor ID
42 amd_id      db  "AuthenticAMD"      ; AMD vendor ID
43 idt_id      db  "CentaurHauls"      ; IDT vendor ID
44
45 CPU_IDT     EQU 01000h              ; Flag for IDT processors
46 CPU_Cyrix   EQU 02000h              ; Flag for Cyrix processors
47 CPU_AMD     EQU 04000h              ; Flag for AMD processors
48 CPU_Intel   EQU 08000h              ; Flag for Intel processors
49
50 enddataseg  _cpuinfo
51
52 begcodeseg  _cpuinfo                ; Start of code segment
53
54 ifdef   USE_NASM
55 %macro mCPU_ID 0
56 db  00Fh,0A2h
57 %endmacro
58 else
59 MACRO   mCPU_ID
60 db  00Fh,0A2h
61 ENDM
62 endif
63
64 ifdef   USE_NASM
65 %macro mRDTSC 0
66 db  00Fh,031h
67 %endmacro
68 else
69 MACRO   mRDTSC
70 db  00Fh,031h
71 ENDM
72 endif
73
74 ;----------------------------------------------------------------------------
75 ; bool _CPU_check80386(void)
76 ;----------------------------------------------------------------------------
77 ; Determines if we have an i386 processor.
78 ;----------------------------------------------------------------------------
79 cprocstart  _CPU_check80386
80
81         enter_c
82
83         xor     edx,edx             ; EDX = 0, not an 80386
84         mov     bx, sp
85 ifdef   USE_NASM
86         and     sp, ~3
87 else
88         and     sp, not 3
89 endif
90         pushfd                      ; Push original EFLAGS
91         pop     eax                 ; Get original EFLAGS
92         mov     ecx, eax            ; Save original EFLAGS
93         xor     eax, 40000h         ; Flip AC bit in EFLAGS
94         push    eax                 ; Save new EFLAGS value on
95                                     ;   stack
96         popfd                       ; Replace current EFLAGS value
97         pushfd                      ; Get new EFLAGS
98         pop     eax                 ; Store new EFLAGS in EAX
99         xor     eax, ecx            ; Can't toggle AC bit,
100                                     ;   processor=80386
101         jnz     @@Done              ; Jump if not an 80386 processor
102         inc     edx                 ; We have an 80386
103
104 @@Done: push    ecx
105         popfd
106         mov     sp, bx
107         mov     eax, edx
108         leave_c
109         ret
110
111 cprocend
112
113 ;----------------------------------------------------------------------------
114 ; bool _CPU_check80486(void)
115 ;----------------------------------------------------------------------------
116 ; Determines if we have an i486 processor.
117 ;----------------------------------------------------------------------------
118 cprocstart  _CPU_check80486
119
120         enter_c
121
122 ; Distinguish between the i486 and Pentium by the ability to set the ID flag
123 ; in the EFLAGS register. If the ID flag is set, then we can use the CPUID
124 ; instruction to determine the final version of the chip. Otherwise we
125 ; simply have an 80486.
126
127 ; Distinguish between the i486 and Pentium by the ability to set the ID flag
128 ; in the EFLAGS register. If the ID flag is set, then we can use the CPUID
129 ; instruction to determine the final version of the chip. Otherwise we
130 ; simply have an 80486.
131
132         pushfd                      ; Get original EFLAGS
133         pop     eax
134         mov     ecx, eax
135         xor     eax, 200000h        ; Flip ID bit in EFLAGS
136         push    eax                 ; Save new EFLAGS value on stack
137         popfd                       ; Replace current EFLAGS value
138         pushfd                      ; Get new EFLAGS
139         pop     eax                 ; Store new EFLAGS in EAX
140         xor     eax, ecx            ; Can not toggle ID bit,
141         jnz     @@1                 ; Processor=80486
142         mov     eax,1               ; We dont have a Pentium
143         jmp     @@Done
144 @@1:    mov     eax,0               ; We have Pentium or later
145 @@Done: leave_c
146         ret
147
148 cprocend
149
150 ;----------------------------------------------------------------------------
151 ; bool _CPU_checkClone(void)
152 ;----------------------------------------------------------------------------
153 ; Checks if the i386 or i486 processor is a clone or genuine Intel.
154 ;----------------------------------------------------------------------------
155 cprocstart  _CPU_checkClone
156
157         enter_c
158
159         mov     ax,5555h            ; Check to make sure this is a 32-bit processor
160         xor     dx,dx
161         mov     cx,2h
162         div     cx                  ; Perform Division
163         clc
164         jnz     @@NoClone
165         jmp     @@Clone
166 @@NoClone:
167         stc
168 @@Clone:
169         pushfd
170         pop     eax                 ; Get the flags
171         and     eax,1
172         xor     eax,1               ; EAX=0 is probably Intel, EAX=1 is a Clone
173
174         leave_c
175         ret
176
177 cprocend
178
179 ;----------------------------------------------------------------------------
180 ; bool _CPU_haveCPUID(void)
181 ;----------------------------------------------------------------------------
182 ; Determines if we have support for the CPUID instruction.
183 ;----------------------------------------------------------------------------
184 cprocstart  _CPU_haveCPUID
185
186         enter_c
187
188 ifdef flatmodel
189         pushfd                      ; Get original EFLAGS
190         pop     eax
191         mov     ecx, eax
192         xor     eax, 200000h        ; Flip ID bit in EFLAGS
193         push    eax                 ; Save new EFLAGS value on stack
194         popfd                       ; Replace current EFLAGS value
195         pushfd                      ; Get new EFLAGS
196         pop     eax                 ; Store new EFLAGS in EAX
197         xor     eax, ecx            ; Can not toggle ID bit,
198         jnz     @@1                 ; Processor=80486
199         mov     eax,0               ; We dont have CPUID support
200         jmp     @@Done
201 @@1:    mov     eax,1               ; We have CPUID support
202 else
203         mov     eax,0               ; CPUID requires 32-bit pmode
204 endif
205 @@Done: leave_c
206         ret
207
208 cprocend
209
210 ;----------------------------------------------------------------------------
211 ; uint _CPU_checkCPUID(void)
212 ;----------------------------------------------------------------------------
213 ; Determines the CPU type using the CPUID instruction.
214 ;----------------------------------------------------------------------------
215 cprocstart  _CPU_checkCPUID
216
217         enter_c
218
219         xor     eax, eax            ; Set up for CPUID instruction
220         mCPU_ID                     ; Get and save vendor ID
221         cmp     eax, 1              ; Make sure 1 is valid input for CPUID
222         jl      @@Fail              ; We dont have the CPUID instruction
223         xor     eax,eax             ; Assume vendor is unknown
224
225 ; Check for GenuineIntel processors
226
227         LEA_L   esi,intel_id
228         cmp     [DWORD esi], ebx
229         jne     @@NotIntel
230         cmp     [DWORD esi+4], edx
231         jne     @@NotIntel
232         cmp     [DWORD esi+8], ecx
233         jne     @@NotIntel
234         mov     eax,CPU_Intel       ; Flag that we have GenuineIntel
235         jmp     @@FoundVendor
236
237 ; Check for CyrixInstead processors
238
239 @@NotIntel:
240         LEA_L   esi,cyrix_id
241         cmp     [DWORD esi], ebx
242         jne     @@NotCyrix
243         cmp     [DWORD esi+4], edx
244         jne     @@NotCyrix
245         cmp     [DWORD esi+8], ecx
246         jne     @@NotCyrix
247         mov     eax,CPU_Cyrix       ; Flag that we have CyrixInstead
248         jmp     @@FoundVendor
249
250 ; Check for AuthenticAMD processors
251
252 @@NotCyrix:
253         LEA_L   esi,amd_id
254         cmp     [DWORD esi], ebx
255         jne     @@NotAMD
256         cmp     [DWORD esi+4], edx
257         jne     @@NotAMD
258         cmp     [DWORD esi+8], ecx
259         jne     @@NotAMD
260         mov     eax,CPU_AMD         ; Flag that we have AuthenticAMD
261         jmp     @@FoundVendor
262
263 ; Check for CentaurHauls processors
264
265 @@NotAMD:
266         LEA_L   esi,idt_id
267         cmp     [DWORD esi], ebx
268         jne     @@NotIDT
269         cmp     [DWORD esi+4], edx
270         jne     @@NotIDT
271         cmp     [DWORD esi+8], ecx
272         jne     @@NotIDT
273         mov     eax,CPU_IDT         ; Flag that we have AuthenticIDT
274         jmp     @@FoundVendor
275
276 @@NotIDT:
277
278 @@FoundVendor:
279         push    eax
280         xor     eax, eax
281         inc     eax
282         mCPU_ID                     ; Get family/model/stepping/features
283         and     eax, 0F00h
284         shr     eax, 8              ; Isolate family
285         and     eax, 0Fh
286         pop     ecx
287         or      eax,ecx             ; Combine in the clone flag
288 @@Done: leave_c
289         ret
290
291 @@Fail: xor     eax,eax
292         jmp     @@Done
293
294 cprocend
295
296 ;----------------------------------------------------------------------------
297 ; uint _CPU_getCPUIDModel(void)
298 ;----------------------------------------------------------------------------
299 ; Determines the CPU type using the CPUID instruction.
300 ;----------------------------------------------------------------------------
301 cprocstart  _CPU_getCPUIDModel
302
303         enter_c
304
305         xor     eax, eax            ; Set up for CPUID instruction
306         mCPU_ID                     ; Get and save vendor ID
307         cmp     eax, 1              ; Make sure 1 is valid input for CPUID
308         jl      @@Fail              ; We dont have the CPUID instruction
309         xor     eax, eax
310         inc     eax
311         mCPU_ID                     ; Get family/model/stepping/features
312         and     eax, 0F0h
313         shr     eax, 4              ; Isolate model
314 @@Done: leave_c
315         ret
316
317 @@Fail: xor     eax,eax
318         jmp     @@Done
319
320 cprocend
321
322 ;----------------------------------------------------------------------------
323 ; uint _CPU_getCPUIDStepping(void)
324 ;----------------------------------------------------------------------------
325 ; Determines the CPU type using the CPUID instruction.
326 ;----------------------------------------------------------------------------
327 cprocstart  _CPU_getCPUIDStepping
328
329         enter_c
330
331         xor     eax, eax            ; Set up for CPUID instruction
332         mCPU_ID                     ; Get and save vendor ID
333         cmp     eax, 1              ; Make sure 1 is valid input for CPUID
334         jl      @@Fail              ; We dont have the CPUID instruction
335         xor     eax, eax
336         inc     eax
337         mCPU_ID                     ; Get family/model/stepping/features
338         and     eax, 00Fh           ; Isolate stepping
339 @@Done: leave_c
340         ret
341
342 @@Fail: xor     eax,eax
343         jmp     @@Done
344
345 cprocend
346
347 ;----------------------------------------------------------------------------
348 ; uint _CPU_getCPUIDFeatures(void)
349 ;----------------------------------------------------------------------------
350 ; Determines the CPU type using the CPUID instruction.
351 ;----------------------------------------------------------------------------
352 cprocstart  _CPU_getCPUIDFeatures
353
354         enter_c
355
356         xor     eax, eax            ; Set up for CPUID instruction
357         mCPU_ID                     ; Get and save vendor ID
358         cmp     eax, 1              ; Make sure 1 is valid input for CPUID
359         jl      @@Fail              ; We dont have the CPUID instruction
360         xor     eax, eax
361         inc     eax
362         mCPU_ID                     ; Get family/model/stepping/features
363         mov     eax, edx
364 @@Done: leave_c
365         ret
366
367 @@Fail: xor     eax,eax
368         jmp     @@Done
369
370 cprocend
371
372 ;----------------------------------------------------------------------------
373 ; uint _CPU_getCacheSize(void)
374 ;----------------------------------------------------------------------------
375 ; Determines the CPU cache size for Intel processors
376 ;----------------------------------------------------------------------------
377 cprocstart  _CPU_getCacheSize
378
379         enter_c
380         xor     eax, eax            ; Set up for CPUID instruction
381         mCPU_ID                     ; Get and save vendor ID
382         cmp     eax,2               ; Make sure 2 is valid input for CPUID
383         jl      @@Fail              ; We dont have the CPUID instruction
384         mov     eax,2
385         mCPU_ID                     ; Get cache descriptors
386         LEA_L   esi,cache_id        ; Get address of cache ID (-fPIC aware)
387         shr     eax,8
388         mov     [esi+0],eax
389         mov     [esi+3],ebx
390         mov     [esi+7],ecx
391         mov     [esi+11],edx
392         xor     eax,eax
393         LEA_L   esi,cache_id        ; Get address of cache ID (-fPIC aware)
394         mov     edi,15
395 @@ScanLoop:
396         cmp     [BYTE esi],41h
397         mov     eax,128
398         je      @@Done
399         cmp     [BYTE esi],42h
400         mov     eax,256
401         je      @@Done
402         cmp     [BYTE esi],43h
403         mov     eax,512
404         je      @@Done
405         cmp     [BYTE esi],44h
406         mov     eax,1024
407         je      @@Done
408         cmp     [BYTE esi],45h
409         mov     eax,2048
410         je      @@Done
411         inc     esi
412         dec     edi
413         jnz     @@ScanLoop
414
415 @@Done: leave_c
416         ret
417
418 @@Fail: xor     eax,eax
419         jmp     @@Done
420
421 cprocend
422
423 ;----------------------------------------------------------------------------
424 ; uint _CPU_have3DNow(void)
425 ;----------------------------------------------------------------------------
426 ; Determines the CPU type using the CPUID instruction.
427 ;----------------------------------------------------------------------------
428 cprocstart  _CPU_have3DNow
429
430         enter_c
431
432         mov     eax,80000000h       ; Query for extended functions
433         mCPU_ID                     ; Get extended function limit
434         cmp     eax,80000001h
435         jbe     @@Fail              ; Nope, we dont have function 800000001h
436         mov     eax,80000001h       ; Setup extended function 800000001h
437         mCPU_ID                     ; and get the information
438         test    edx,80000000h       ; Bit 31 is set if 3DNow! present
439         jz      @@Fail              ; Nope, we dont have 3DNow support
440         mov     eax,1               ; Yep, we have 3DNow! support!
441 @@Done: leave_c
442         ret
443
444 @@Fail: xor     eax,eax
445         jmp     @@Done
446
447 cprocend
448
449 ;----------------------------------------------------------------------------
450 ; ulong _CPU_quickRDTSC(void)
451 ;----------------------------------------------------------------------------
452 ; Reads the time stamp counter and returns the low order 32-bits
453 ;----------------------------------------------------------------------------
454 cprocstart  _CPU_quickRDTSC
455
456         mRDTSC
457         ret
458
459 cprocend
460
461 ;----------------------------------------------------------------------------
462 ; void _CPU_runBSFLoop(ulong interations)
463 ;----------------------------------------------------------------------------
464 ; Runs a loop of BSF instructions for the specified number of iterations
465 ;----------------------------------------------------------------------------
466 cprocstart  _CPU_runBSFLoop
467
468         ARG     iterations:ULONG
469
470         push    _bp
471         mov     _bp,_sp
472         push    _bx
473
474         mov     edx,[iterations]
475         mov     eax,80000000h
476         mov     ebx,edx
477
478         ALIGN   4
479
480 @@loop: bsf     ecx,eax
481         dec     ebx
482         jnz     @@loop
483
484         pop     _bx
485         pop     _bp
486         ret
487
488 cprocend
489
490 ;----------------------------------------------------------------------------
491 ; void  _CPU_readTimeStamp(CPU_largeInteger *time);
492 ;----------------------------------------------------------------------------
493 ; Reads the time stamp counter and returns the 64-bit result.
494 ;----------------------------------------------------------------------------
495 cprocstart  _CPU_readTimeStamp
496
497         mRDTSC
498         mov     ecx,[esp+4]     ; Access directly without stack frame
499         mov     [ecx],eax
500         mov     [ecx+4],edx
501         ret
502
503 cprocend
504
505 ;----------------------------------------------------------------------------
506 ; ulong _CPU_diffTime64(CPU_largeInteger *t1,CPU_largeInteger *t2,CPU_largeInteger *t)
507 ;----------------------------------------------------------------------------
508 ; Computes the difference between two 64-bit numbers.
509 ;----------------------------------------------------------------------------
510 cprocstart  _CPU_diffTime64
511
512         ARG     t1:DPTR, t2:DPTR, t:DPTR
513
514         enter_c
515
516         mov     ecx,[t2]
517         mov     eax,[ecx]       ; EAX := t2.low
518         mov     ecx,[t1]
519         sub     eax,[ecx]
520         mov     edx,eax         ; EDX := low difference
521         mov     ecx,[t2]
522         mov     eax,[ecx+4]     ; ECX := t2.high
523         mov     ecx,[t1]
524         sbb     eax,[ecx+4]     ; EAX := high difference
525
526         mov     ebx,[t]         ; Store the result
527         mov     [ebx],edx       ; Store low part
528         mov     [ebx+4],eax     ; Store high part
529         mov     eax,edx         ; Return low part
530 ifndef flatmodel
531         shld    edx,eax,16      ; Return in DX:AX
532 endif
533         leave_c
534         ret
535
536 cprocend
537
538 ;----------------------------------------------------------------------------
539 ; ulong _CPU_calcMicroSec(CPU_largeInteger *count,ulong freq);
540 ;----------------------------------------------------------------------------
541 ; Computes the value in microseconds for the elapsed time with maximum
542 ; precision. The formula we use is:
543 ;
544 ;   us = (((diff * 0x100000) / freq) * 1000000) / 0x100000)
545 ;
546 ; The power of two multiple before the first divide allows us to scale the
547 ; 64-bit difference using simple shifts, and then the divide brings the
548 ; final result into the range to fit into a 32-bit integer.
549 ;----------------------------------------------------------------------------
550 cprocstart  _CPU_calcMicroSec
551
552         ARG     count:DPTR, freq:ULONG
553
554         enter_c
555
556         mov     ecx,[count]
557         mov     eax,[ecx]       ; EAX := low part
558         mov     edx,[ecx+4]     ; EDX := high part
559         shld    edx,eax,20
560         shl     eax,20          ; diff * 0x100000
561         div     [DWORD freq]    ; (diff * 0x100000) / freq
562         mov     ecx,1000000
563         xor     edx,edx
564         mul     ecx             ; ((diff * 0x100000) / freq) * 1000000)
565         shrd    eax,edx,20      ; ((diff * 0x100000) / freq) * 1000000) / 0x100000
566 ifndef flatmodel
567         shld    edx,eax,16      ; Return in DX:AX
568 endif
569         leave_c
570         ret
571
572 cprocend
573
574 ;----------------------------------------------------------------------------
575 ; ulong _CPU_mulDiv(ulong a,ulong b,ulong c);
576 ;----------------------------------------------------------------------------
577 ; Computes the following with 64-bit integer precision:
578 ;
579 ;   result = (a * b) / c
580 ;
581 ;----------------------------------------------------------------------------
582 cprocstart  _CPU_mulDiv
583
584         ARG     a:ULONG, b:ULONG, c:ULONG
585
586         enter_c
587         mov     eax,[a]
588         imul    [ULONG b]
589         idiv    [ULONG c]
590 ifndef flatmodel
591         shld    edx,eax,16      ; Return in DX:AX
592 endif
593         leave_c
594         ret
595
596 cprocend
597
598 endcodeseg  _cpuinfo
599
600         END