ifdef FP87 _Emu_ equ 0 ; no emulation, '87 required else _Emu_ equ 1 ; emulator endif public FIDRQQ ; wait, esc public FIARQQ ; wait, DS: public FICRQQ ; wait, CS: public FIERQQ ; wait, ES: public FISRQQ ; wait, SS: public FIWRQQ ; nop, wait public FJARQQ ; Esc nn -> DS:nn public FJCRQQ ; Esc nn -> CS:nn public FJSRQQ ; Esc nn -> ES:nn ; Use full emulator if _Emu_ is true. if _Emu_ FIDRQQ equ 05C32h FIARQQ equ 0FE32h FICRQQ equ 00E32h FIERQQ equ 01632h FISRQQ equ 00632h FIWRQQ equ 0A23Dh FJARQQ equ 04000h FJCRQQ equ 0C000h FJSRQQ equ 08000h else FIDRQQ equ 00000h FIARQQ equ 00000h FICRQQ equ 00000h FIERQQ equ 00000h FISRQQ equ 00000h FIWRQQ equ 00000h FJARQQ equ 00000h FJCRQQ equ 00000h FJSRQQ equ 00000h endif originalVectors dd 0Ch dup(?) FPEpriorVector dd ? fpinit_platform db 0 fpinit_100B5 dw 0FFFFh fpinit_100B7 db ? fpinit_100B8 db 0 plus_inf dd 7F800000h ; borrowed from T. Pascal, DOS 3.1 BIOS ; avoid DOS 3.2 stack swap int75handler proc far push ax xor al, al ; Clear BUSY latch out 0F0h, al mov al, 20H ; End-of-interrupt out 0A0h, al out 20h, al pop ax int 2 iret int75handler endp nec_fpinit_100CC proc near push ax mov al, 20h out 8, al jmp short $+2 mov al, 0Bh out 8, al jmp short $+2 in al, 8 or al, al jnz short @@loc_100E3 mov al, 20h out 0, al @@loc_100E3: pop ax jmp short $+2 nec_fpinit_100CC endp int2handler proc far push ax mov ax, seg __emu call e087_Trap jb short @@err pop ax ; --------------------------------------------------------------------------- db 0EAh nmi dw 2 dup(?) ; --------------------------------------------------------------------------- @@err: xchg ax, bx mov ax, seg __8087 mov ds, ax call __fperror pop ax int2handler_ret: iret int2handler endp emu1st proc near push ds push si push di mov ax, seg __8087 mov ds, ax ; set end of FPU stack mov ax, offset __emu + SIZE_FPU mov word ptr ss:__emu+0Fh, ax add ax, 0C0h mov word ptr ss:__emu+11h, ax mov ax, __protected mov word ptr ss:__emu+7, ax push ds push cs pop ds ; assume ds:nothing mov ax, ds xor ax, word ptr ss:__emu+7 mov ds, ax ; assume ds:DGROUP mov ax, 3534h mov cx, 11 mov di, offset originalVectors @@rememberLoop: int 21h mov [di], bx mov word ptr [di+2], es add di, 4 inc ax loop @@rememberLoop push ds push di mov cl, 0 mov ax, seg __8087 mov ds, ax cmp __8087, 0 jz short @@IBM mov ah, 4 xor cx, cx int 1Ah mov cl, 2 cmp ch, 19h jz short @@IBM cmp ch, 20h jz short @@IBM mov cl, 1 @@IBM: pop di pop ds assume ds:seg fpinit_platform mov ds:fpinit_platform, cl cmp cl, 2 jnz short @@loc_10182 ; grab INT 75h mov ax, 3575h int 21h mov [di], bx mov word ptr [di+2], es add di, 4 ; grab INT 2 mov ax, 3502h jmp short @@loc_10199 @@loc_10182: cmp cl, 1 jnz short @@loc_101B0 push sp pop ax cmp ax, sp mov ax, 3510h jz short @@loc_10199 in al, 0Ah and al, 40h mov ds:fpinit_100B7, al mov al, 16h @@loc_10199: mov bl, al mov bh, 25h mov ds:fpinit_100B5, bx int 21h mov [di], bx mov word ptr [di+2], es mov ds:nmi, bx mov ds:nmi+2, es @@loc_101B0: pop ds assume ds:seg __psp mov bx, -1 mov es, __psp ; Look for a "87" environment variable. ; Each variable is ended by a 0 and a zero-length variable stops ; the environment. The environment can NOT be greater than 32k. ; assume es:nothing mov es, word ptr es:2Ch ; environment segment ; assume es:nothing sub di, di ; ES:[di] points to environ mov cx, 7FFFh ; Environment cannot be > 32 Kbytes mov al, 0 cld @@env87next: repne scasb ; direction flag is clear jcxz short @@env87done ; count exhausted imply end cmp al, es:[di] ; double zero bytes imply end jz short @@env87done cmp word ptr es:[di], '78' jnz short @@env87next mov dx, es:[di+2] cmp dl, '=' jnz short @@env87next inc bx and dh, not ('y' - 'Y') cmp dh, 'Y' jnz short @@env87done inc bx @@env87done: pop di pop si xor ax, ax or bx, bx jz short @@set_flag jg short @@loc_1022E mov cx, __8087 jcxz short @@loc_10250 @@TestPresence: fninit mov __8087, 0 fnstcw __8087 mov cx, 20 @@delay_1: loop @@delay_1 ; Delay awhile mov cx, __8087 ; Get NPX control word and cx, 0F3Fh ; Mask off undefined bits cmp cx, 33Fh ; Do we have a math coprocessor jnz short @@test_done ; No ... mov __8087, -1 fnstsw __8087 ; Store the status word mov cx, 14h @@delay_2: loop @@delay_2 ; Delay awhile test __8087, 0B8BFh ; All bits off that should be? jnz short @@test_done @@loc_1022E: inc ax push sp pop cx cmp cx, sp jnz short @@test_done fninit fld cs:plus_inf fchs fcomp cs:plus_inf ; compare +INF to -INF fstsw ax ; we have a 287 or better sahf mov al, 2 jz short @@test_done ; equal on 80287 only inc ax @@test_done: cbw @@set_flag: mov __8087, ax @@loc_10250: mov ss:__emu+6, al pop ds emu1st endp option emulator public ___fpreset ___fpreset proc near @@temp1 = dword ptr -8 @@temp2 = dword ptr -4 push ds push bp mov bp, sp sub sp, 8 mov bx, seg __8087 mov ds, bx cmp __8087, 0 mov word ptr [bp+@@temp1], offset e087_Entry mov word ptr [bp+@@temp1+2], seg e087_Entry mov word ptr [bp+@@temp2], offset e087_Shortcut mov word ptr [bp+@@temp2+2], seg e087_Shortcut jnz short @@doCapture mov word ptr [bp+@@temp1], offset e086_Entry mov word ptr [bp+@@temp1+2], seg e086_Entry mov word ptr [bp+@@temp2], offset e086_Shortcut mov word ptr [bp+@@temp2+2], seg e086_Shortcut @@doCapture: mov ax, 2534h mov cx, 10 lds dx, [bp+@@temp1] @@captureLoop: int 21h inc ax loop @@captureLoop mov ax, 253Eh lds dx, [bp+@@temp2] int 21h mov ds, bx cmp __8087, 0 jnz short @@loc_102D8 mov word ptr ss:__emu+41h, offset int2handler mov word ptr ss:__emu+43h, cs push cs pop ds mov ax, ds xor ax, word ptr ss:__emu+7 mov ds, ax assume ds:seg nmi mov ds:nmi, offset int2handler_ret mov ds:nmi+2, cs mov ds:fpinit_100B5, -1 jmp short @@init87 @@loc_102D8: push cs pop ds cmp ds:fpinit_platform, 2 jnz short @@loc_10306 mov ax, ds:fpinit_100B5 mov dx, offset int2handler int 21h mov ds, bx assume ds:seg __8087 cmp __8087, 0 jz short @@init87 mov ax, __version xchg ah, al cmp ax, 1403h jnz short @@init87 mov ax, 2575h push cs pop ds assume ds:seg fpinit_platform mov dx, offset int75handler int 21h @@loc_10306: cmp ds:fpinit_platform, 1 jnz short @@init87 mov ax, ds:fpinit_100B5 mov dx, offset int2handler cmp al, 16h jnz short @@loc_1031A mov dx, offset nec_fpinit_100CC @@loc_1031A: int 21h cmp al, 16h jnz short @@init87 pushf cli in al, 0Ah and al, 0BFh out 0Ah, al popf @@init87: mov ds, bx mov cs:fpinit_100B8, 1 ; Hack (this is not assembling to an emulated fninit for some reason?) db 0CDh, 037h, 0E3h mov word ptr ss:__emu+21h, 0 mov word ptr ss:__emu+23h, 0 assume ds:seg __default87 mov ax, __default87 mov word ptr [bp+@@temp1], ax cmp __8087, 3 jl short @@control or word ptr [bp+@@temp1], 2 @@control: push si fldcw word ptr [bp+@@temp1] pop si mov ax, word ptr [bp+@@temp1] and word ptr ss:__emu+2, ax xor ax, ax cwd mov sp, bp pop bp pop ds ret ___fpreset endp public emuLast emuLast proc near push ds mov ax, seg __8087 mov ds, ax cmp cs:fpinit_100B8, 0 jz short @@done push ds finit mov ax, 2534h mov bx, offset originalVectors mov cx, 11 @@restoreLoop: lds dx, cs:[bx] assume ds:seg __8087 int 21h add bx, 4 inc ax loop @@restoreLoop pop ds cmp __8087, 0 jz short @@done cmp cs:fpinit_platform, 2 jnz short @@loc_103AA mov ax, 2575h lds dx, cs:[bx] int 21h add bx, 4 @@loc_103AA: mov ax, cs:fpinit_100B5 cmp cs:fpinit_platform, 1 jnz short @@loc_103C8 cmp al, 16h jnz short @@loc_103C8 xchg ax, dx pushf cli in al, 0Ah or al, cs:fpinit_100B7 out 0Ah, al popf xchg ax, dx @@loc_103C8: lds dx, cs:[bx] int 21h @@done: mov cs:fpinit_100B8, 0 pop ds ret emuLast endp public __fpuint __fpuint proc far mov ax, cs:fpinit_100B5 ret __fpuint endp