Files
oldlinux-files/study/sabre/os/files/Processors/COPRO.ASM
2024-02-19 00:25:23 -05:00

245 lines
6.8 KiB
NASM

comment *
Purpose:
To detect math coprocessor type (8087, 287, 387) and manufacturer
(Intel, IIT)
*
.model tiny
.data
fnone equ 0
f8087 equ 1
f80287 equ 2
f80387 equ 3
funk equ 0FFh
ndp_cw dw ?
ndp_sw dw ?
mNDPCW dw ?
mndp db ?
ndpmsg db "Math coprocessor found: $"
manmsg db "Manufacturer: $"
_87 db "8087",13,10,"$"
_287 db "80287",13,10,"$"
_387 db "80387 or i486",13,10,"$"
_funk db "What the hell kind of a copro is this?",13,10,"$"
Intel db "Intel or clone",13,10,"$"
IIT db "IIT or clone",13,10,"$"
.code
org 100h
start:
; The next two 80x87 instructions cannot carry the WAIT prefix,
; because there may not be an 80x87 for which to wait. The WAIT is
; therefore emulated with a MOV CX,<value>! LOOP $ combination.
.8087
mov word ptr ndp_cw,0000H
cli ;no interrupts during this test
fninit ;initialize NDP
mov cx,2
loop $
fnstcw ndp_cw ;store control word in ndp_cw
; mov cx,14h
; loop $
sti
mov ax,ndp_cw ;check for valid status word
cmp ah,3 ;is NDP present?
je short ndp_01 ;if 3, must be there
mov mNDP,fnone
jmp short ndp_done
ndp_01:
cmp ax,03FFH ;check if 8087
jne short ndp_02
mov mNDP,f8087
jmp short ndp_04
ndp_02:
call iit_test
.286P
cmp ax,037FH ;check if 286/387/486
jne short ndp_05 ;must be garbage
;detect 287 or 387
fld1 ;Load +1.0 onto NDP stack
fldz ;Load +0.0 onto NDP stack
fdiv ;do +1/0
fld1 ;Load +1.0 onto NDP stack
fchs ;Change to -1.0
fldz ;Load +0.0 onto NDP stack
fdiv ;do -1/0
fcom ;compare
fstsw ndp_sw
mov ax,ndp_sw
and ah,41H ; C3, C0
cmp ah,40H ; ST(0) = ST(1)
jne short ndp_03
mov mNDP,f80287
jmp short ndp_04
ndp_03:
cmp ah,01H ; ST(0) < ST(1)
jne short ndp_05
mov mNDP,f80387
ndp_04:
.8087
fstcw mNDPCW ;save status for INFOPLUS
jmp short ndp_done
ndp_05:
mov mNDP,funk
ndp_done:
mov ah, 9
mov dx, offset manmsg
int 21h
cmp [mman], 1 ;IIT=1?
jne short intelman
mov ah, 9
mov dx, offset iit
int 21h
jmp short type_msgs
intelman:
mov ah, 9
mov dx, offset intel
int 21h
type_msgs:
mov ah, 9
mov dx, offset ndpmsg
int 21h
cmp [mndp], 0FFh
jne short not_funk
mov ah, 9
mov dx, offset _funk
int 21h
jmp short exit_prog
not_funk:
cmp [mndp], 3
jne short not_387
mov ah, 9
mov dx, offset _387
int 21h
jmp short exit_prog
not_387:
cmp [mndp], 2
jne short not_287
mov ah, 9
mov dx, offset _287
int 21h
jmp short exit_prog
not_287:
mov ah, 9
mov dx, offset _87
int 21h
exit_prog:
mov al, [mndp]
mov ah, 4ch
int 21h
iit_test proc near
.data
fsb0 equ <dw 0E8DBh> ;bank 0 opcode
fsb1 equ <dw 0EBDBh> ;bank 1 opcode
fsb2 equ <dw 0EADBh> ;bank 2 opcode
f4x4 equ <dw 0F1DBh> ;4x4 mat transform opcode
f0 dd 9.9999
f1 dd 10.0
mman db 0 ;assume Intel=0 installed initially
.code
;initialize two banks to zero
wait
fsb0 ;switch to bank 0, default on Intel
finit
fsb1 ;switch to bank 1
finit
;store a 2.0 into bank 0 while placing a 1.0 into bank 1
fsb0 ;switch to bank 0
fld [f0] ;load value from [F2] into bank 0 stack
fclex ;clear all math copro exceptions
fsb1 ;switch to bank 1, should fail on Intel
fld [f1] ;load a 1 into bank 1 stack
fclex
fsb0
fcom [f0] ;compare, should be false on Intel
fclex
push ax
.286p ;FNSTSW AX only works on 287+
fnstsw ax ;store stat word in AX
sahf ;transfer copro flags to CPU flags
ja short is_intel
mov [mman], 1 ;IIT=1, Intel=0 (default)
is_intel:
finit ;reset to original
pop ax
ret
endp
end start
iit_test proc near
.data
fsb0 equ <dw 0E8DBh> ;bank 0 opcode
fsb1 equ <dw 0EBDBh> ;bank 1 opcode
fsb2 equ <dw 0EADBh> ;bank 2 opcode
f4x4 equ <dw 0F1DBh> ;4x4 mat transform opcode
f0 dd 9.9999
f1 dd 10.0
mman db 0 ;assume Intel=0 installed initially
.code
;initialize two banks to zero
wait
fsb0 ;switch to bank 0, default on Intel
finit
fsb1 ;switch to bank 1
finit
;store a 2.0 into bank 0 while placing a 1.0 into bank 1
fsb0 ;switch to bank 0
fld [f0] ;load value from [F2] into bank 0 stack
fclex ;clear all math copro exceptions
fsb1 ;switch to bank 1, should fail on Intel
fld [f1] ;load a 1 into bank 1 stack
fclex
fsb0
fcom [f0] ;compare, should be false on Intel
fclex
push ax
.286p ;FNSTSW AX only works on 287+
fnstsw ax ;store stat word in AX
sahf ;transfer copro flags to CPU flags
ja short is_intel
mov [mman], 1 ;IIT=1, Intel=0 (default)
is_intel:
finit ;reset to original
pop ax
ret
endp
end start
; EOF COPRO.ASM