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