Coherent4.2.10/i386/ndpas.s

/ ndpas.s - assembler support for COH386 ndp
	.unixorder
	.globl	ndpSave
	.globl	ndpRestore
	.globl	ndpInit
	.globl	ndpSense

/ void ndpInit(short cw);
ndpInit:
	fninit
	fldcw	4(%esp);
	fwait
	ret

/ void ndpSave(char * bp);
ndpSave:
	mov	4(%esp),%eax
	fsetpm
	fnsave	(%eax)
	fwait
	ret

/ void ndpRestore(char * bp);
ndpRestore:
	mov	4(%esp),%eax
	fsetpm
	frstor	(%eax)
	ret

/ int ndpSense(void)
/ call this with EM bit of CR0 off!
/ return values according to NDP_TYPE_* in ndp.c
ndpSense:
	enter	$0,$4			/ reserve 4 bytes of auto storage
	movl	$1,%eax			/ ret = 1 (NDP_TYPE_NONE)
	movw	$0xffff,-4(%ebp)	/ write 2 bytes of f's
	fninit				/ reset FP status word, if any
	fnstsw	-4(%ebp)		/ write SW to memory (should be zero)
	cmpw	$0,-4(%ebp)		/ did we clear memory?
	jnz	x01			/ if not, NDP_TYPE_NONE
	fnstcw	-4(%ebp)		/ now try to write a control word
	andw	$0x103f,-4(%ebp)	/ mask bits not to be checked
	cmpw	$0x003f,-4(%ebp)
	jne	x01			/ didn't get expected bits - no NDP

/ At this point, we know there is an NDP.

/ Is there a 486? if so, ndp type is 486DX/487SX
	mov	%esp,%ecx		/ save esp in ecx
	andl	$~3,%esp		/ round esp down to 4-byte boundary
	pushfl
	popl	%eax			/ get PSW into eax
	mov	%eax,%edx		/ save original PSW to edx
	xorl	$0x40000,%eax		/ flip AC bit (only exists in 486)
	andw	$~0x0200,%ax		/ interrupts off for this!

	pushl	%eax			/ put back into flags reg
	popfl
	pushfl				/ get flags again.  ho hum.
	popl	%eax

	pushl	%edx			/ restore old PSW
	popfl
	mov	%ecx,%esp		/ restore old esp

	xor	%edx,%eax		/ compare old and new PSW's
	and	$0x40000,%eax		/ only care about AC bit
	movl	$4,%eax			/ ret = NDP_TYPE_486DX
	jne	x01

/ By elimination, system consists of 386 plus either 287 or 387.
/ Find out which.  Remember, exceptions are now masked.
	fld1
	fldz
	fdivr				/ leave 1.0/0.0 on FP stack
	fld	%st			/ duplicate infinity
	fchs				/ negate
	fcompp				/ compare and pop FP
	fstsw	-4(%ebp)		/ write FP flags
	movw	-4(%ebp),%ax
	sahf				/ FP flags to PSW
	movl	$3,%eax			/ ret = NDP_TYPE_387
	jne	x01
	dec	%eax			/ ret = NDP_TYPE_286

x01:
	leave
	ret