;
; FPU.ASM (c) Rainer Schnitker 92,93
;

;
; 387 utils
;

	.286
	.model SMALL, C

	.data

	extrn	emu_entry:PWORD
	extrn	emu_sel:WORD
	extrn	emu_esp:DWORD
	havei387    dw	    0

	.code

;
; DWORD emu_init( void ) : call emu387 to get copro struct
;
; emu should init exception vector 7
;
	public C emu_init
emu_init Proc C USES DI SI,
	.386
	push	gs
	mov	eax,12345678H
	mov	gs,emu_sel
	mov	edx,emu_esp
	call	pword ptr emu_entry
	; convert eax = copro-struct in dx:ax
	mov	edx,eax
	shr	edx,16
	and	eax,dword ptr 0FFFFh
	pop	gs
	.286
	ret
emu_init endp

;
; void emu_switch( WORD , WORD ) : call emu387, to change process status
;
	public C emu_switch
emu_switch PROC C \
	used_math	:WORD , \
	debugged	:WORD
	.386
	push	gs
	mov	gs,emu_sel
	movzx	ecx,used_math
	movzx	edx,debugged
	call	pword ptr emu_entry
	pop	gs
	.286
	ret
emu_switch endp

;
; void do_fnsave( unsigned fpu_struct )
;
	public C do_fnsave
do_fnsave PROC C \
	fpu_struct	:WORD

	.386
	movzx	eax,word ptr fpu_struct
	db 066H
	fnsave	[eax]
	fwait
	.286
	ret
do_fnsave endp

;
; void do_frstor( unsigned fpu_struct )
;
	public C do_frstor
do_frstor PROC C \
	fpu_struct	:WORD

	.386
	movzx	eax,word ptr fpu_struct
	db 066H
	frstor	[eax]
	fwait
	.286
	ret
do_frstor endp

;
; void do_fninit(void)
;
	public C do_fninit
do_fninit PROC C
	fninit
	ret
do_fninit endp


	public C npx_installed
npx_installed PROC C USES SI,

	fninit					; set SW,CW,..
	mov	si, offset havei387
	mov	word ptr [si],5a5ah
	fnstsw	[si]				; save SW
	cmp	byte ptr [si],0 		; SW==0 ?
	jne	no_i387

	fnstcw	[si]				; save CW
	mov	ax,[si] 			; check
	and	ax,103fh			;
	cmp	ax,3fh				; init ?
	jne	no_i387

	fld1					; check for 387
	fldz
	fdiv
	fld	st
	fchs
	fcompp
	fstsw	[si]
	mov	ax,[si]
	sahf
	je	no_i387
	fninit					; 387 ok ,init
	fnstcw	havei387
	wait
	and	havei387,0fffah
	fldcw	havei387
	mov	ax,1
	jmp	short ende
no_i387:
	mov	ax,0
ende:
	ret
npx_installed endp

	end
