home *** CD-ROM | disk | FTP | other *** search
- .model tiny
-
- .data
- bugnr dt 824633702449.0
- diff dt ?
-
- feature_bits dd ?
-
- cpu_msg dw I808x$, I186$, I286$, I386$, I486$, cpuid5$
- ndp_msg dw No87$, I8087$, I287$, I387$
-
- feature_list dw fpu$, vme$, iobrk$, pse$, tsc$, p5msr$, 0, mce$, cx8$
-
- cprt db 'Pentium FDIV bug finder. V1.1 (c) Terje Mathisen 1994'
- db 13,10,13,10,'$'
-
- I808x$ db 'This is an 808x cpu',13,10,'$'
- I186$ db 'This is a 186 cpu',13,10,'$'
- I286$ db 'This is a 286 cpu',13,10,'$'
- I386$ db 'This is a 386 cpu',13,10,'$'
- I486$ db 'This is a 486 cpu',13,10,'$'
- cpuid5$ db 'This is a Pentium or better cpu',13,10,'$'
-
- No87$ db 'It has no ndp!',13,10,'$'
- I8087$ db 'It has an 8087 ndp',13,10,'$'
- I287$ db 'It has a 287 ndp',13,10,'$'
- I387$ db 'It has a 387 or later ndp',13,10,'$'
-
- feature_msg1$ db 13,10,'CPU feature list:',13,10
-
- fpu$ db ' 1 : FPU (NDP) onchip',13,10,'$'
- vme$ db ' 2 : Virtual 86 Mode Extensions',13,10,'$'
- iobrk$ db ' 4 : I/O Breakpoints',13,10,'$'
- pse$ db ' 8 : Page Size Extensions',13,10,'$'
- tsc$ db ' 10 : Time Stamp Counter',13,10,'$'
- p5msr$ db ' 20 : Pentium style Model Specific Registers',13,10,'$'
- mce$ db ' 80 : Machine Check Exception',13,10,'$'
- cx8$ db '100 : CMPXCHG8B instruction available',13,10,13,10,'$'
-
- feature_msg2$ db '$'
-
- earlyP5$ db 'This is an early Pentium, with only partial CPUID support!',13,10,'$'
-
- cpuid_result$ db 13,10,'CPUID reports back:',13,10
- db 'Vendor id = "'
- vendor_id dd 3 dup (?)
- db '"',13,10
- db 'Family (4=486, 5=Pentium etc.) = '
- make$ dw '00'
- db ', stepping = '
- step$ dw '00'
- db ', model = '
- model$ dw '00'
- db 13,10,'$'
-
- FPU_bug$ db 13,10,'It has the FDIV bug:',13,10
- db '(1.0/824633702449.0)*824633702449.0 is not equal to 1.0!',13,10,'$'
-
- FPU_OK$ db 13,10,'It does not have the FDIV bug!',13,10,'$'
-
- stepping db ?
- CPUModel db ?
- Cpu_Type db ? ; 0,1,2,3,4,5 etc
- Ndp_Type db ? ; None, 8087, 287, 387+
- have_cpuid db 0
-
- Notp5$ db 'The FDIV bug occurs only on Pentium cpus!',13,10,'$'
-
- .code
- org 100h
- start proc far
-
- lea dx,[cprt]
- mov ah,9
- int 21h
-
- call getcpu
-
- mov bl,[cpu_type]
- cmp bl,5
- jbe @@ok
- mov bl,5
- @@ok:
- xor bh,bh
- add bx,bx
- mov dx,cpu_msg[bx]
- mov ah,9
- int 21h
-
- test [have_cpuid],-1
- jz no_cpuid
-
- mov bx, word ptr [feature_bits]
- mov ax, word ptr [feature_bits+2]
- or ax,bx
- lea dx,[earlyP5$]
- jz dispMsg
-
- ;
- ; We have full CPUID support on this cpu, report back what we found!
- ;
- mov al,[stepping]
- xor ah,ah
- mov bl,10
- div bl
- add ax,'00'
- mov [step$],ax
-
- mov al,[CpuModel]
- xor ah,ah
- div bl
- add ax,'00'
- mov [model$],ax
-
- mov al,[cpu_type]
- xor ah,ah
- div bl
- add ax,'00'
- mov [make$],ax
-
- lea dx,[cpuid_result$]
- mov ah,9
- int 21h
- ;
- ; Display feature bits definitions:
- ;
- lea dx,[feature_msg1$]
- mov ah,9
- int 21h
-
- lea si,[feature_list-2]
- mov cx,9 ; Nr of currently defined feature bits
- mov di,word ptr [feature_bits]
-
- @@next_feature:
- add si,2
- shr di,1
- jnc @@skip_feature
- mov dx,[si]
- mov ah,9
- int 21h
-
- @@skip_feature:
- dec cx
- jnz @@next_feature
-
- lea dx,[feature_msg2$]
- dispMsg:
- mov ah,9
- int 21h
-
- no_cpuid:
- call getndp
- mov bl,[ndp_type]
- cmp bl,3
- jbe @@ndp_ok
- mov bl,3
- @@ndp_ok:
- xor bh,bh
- add bx,bx
- mov dx,ndp_msg[bx]
- mov ah,9
- int 21h
-
- test bx,bx
- jz exit ; No NDP, so no NDP bug either! :-)
-
- call testndp
- lea dx,[FPU_OK$]
- jz @@disp_bug
- lea dx,[FPU_Bug$]
- @@disp_bug:
- mov ah,9
- int 21h
-
- exit:
- mov ax,4c00h
- int 21h ; All done!
- start endp
-
- getcpu proc ; return 0,1,2,3,4,5 etc in BL for 808x,186,286,386...
-
- pushf
- pop ax
- and ah,0fh ; Try to clear four upper flag bits!
- push ax
- popf
- pushf
- pop ax
- xor bx,bx ; Assume 808x -> BX = 0
- cmp ah,0f0h
- jae getcpu_done ; All four upper bits set -> 808x!
-
- or ah,0f0h ; Try to set the upper four bits:
- push ax
- popf
- pushf
- pop ax
- and ah,0f0h ; Isolate them
- mov bx,2 ; This is a 286!
- jz getcpu_done ; Just a 286, no FDIV problem!
- ;
- ; *************** 386+ code *******************
- ;
- inc bx ; BX = 3, for 386+ cpus
-
- .486
- mov edx,esp
- and esp,not 3 ; DWORD-align the stack to allow AC!
-
- pushfd
- pop eax
- mov ecx,eax
- xor eax,1 SHL 18 ; AC flag == bit # 18!
- push eax
- popfd
- pushfd
- pop eax
- push ecx
- popfd ; Restore original eflags
- mov esp,edx ; Restore word-aligned stack ptr
-
- xor eax,ecx ; Could we toggle the AC flag?
- jz getcpu_done ; No, so this is a 386!
-
- inc bx ; BX = 4(86)
- mov eax,ecx
- xor eax,1 SHL 21 ; ID flag == bit # 21!
- push eax
- popfd
- pushfd
- pop eax
- push ecx
- popfd
- xor eax,ecx ; Could we toggle the ID bit?
- jnz haveCPUID ; Yes, so use CPUID to get more info!
-
- ; Drop through to exit for 486 case
- getcpu_done:
- mov [cpu_type],bl
- ret ; Return with BX = CPU ID
-
- haveCPUID:
- mov [have_cpuid],1 ; At least some support for CPUID
-
- ; Use CPUID instruction to get more info!
- xor eax,eax ; EAX == 0 -> Basic CPUID report
- db 0Fh, 0A2h ; CPUID opcode!
-
- mov [vendor_id],ebx
- mov [vendor_id+4],edx
- mov [vendor_id+8],ecx
- test eax,eax ; Are other values in EAX valid?
- jz getcpu_done ; No, so this is an early Pentium!
-
- mov eax,1
- db 0Fh, 0A2h ; CPUID opcode!
- mov [feature_bits],edx
- and ah,15 ; CPU Family [4(486), 5 (Pentium) etc]
- mov [cpu_type],ah ; Save it! (Return value)
- mov bl,ah
- xor bh,bh
-
- mov ah,al
- shr ah,4
- and al,15
- mov [stepping],al
- mov [CpuModel],ah
- .8086
-
- ret
- getcpu endp
-
- .data
- cw dw ?
-
- .code
-
- getndp proc
- fninit
- xor dx,dx ; DL = (NO87, 8087, 287, 387+)
- mov bx,offset cw
- mov [bx],dx ; Make sure ControlWord is zero!
- fnstcw [bx]
- jmp $+2 ; Wait for result
- jmp $+2 ; Wait for result
- jmp $+2 ; Wait for result
- cmp byte ptr [bx+1],03
- jne ndpdone ; NO 87 installed!
-
- fdisi ; Try to Disable x87 interrupts
- fstcw [bx]
- inc dx ; At least 8087
- fwait ; Wait for result from FSTCW
- test byte ptr [bx],80h ; DISI bit set?
- jnz ndpdone ; Yes, it's a 8087
-
- .286
- .287
- inc dx ; 80287 or 80387
- fld1 ; 1.0
- fldz ; 0.0
- fdivp st(1),st ; 1.0 / 0.0 = +Inf
- fld st(0) ; Duplicate
- fchs ; = -Inf
- fcompp ; Are +Inf equal to -Inf?
- fwait ; Wait for result
- fstsw ax
- sahf ; Status from float point cmp
- je ndpdone ; +Inf == -Inf => 287
- inc dx ; 387
- .8086
- .8087
- ndpdone:
- mov [ndp_type],dl
- ret
-
- getndp endp
-
- testndp proc
- ; Check for FPU bug: Return Z(ero)/NonZero for OK/Bad
-
- finit
- fld1
- fld [bugnr]
- fdivp st(1),st
- fld [bugnr]
- fmulp st(1),st
- fld1
- fsubp st(1),st
- fstp [diff]
- fwait
- mov ax,word ptr [diff+6]
- and ah,3fh ; Throw away two MS bits
- or ax,word ptr [diff]
- or ax,word ptr [diff+2]
- or ax,word ptr [diff+4]
- ret
- testndp endp
-
- end start
-
-