Mail Archives: djgpp/1996/10/24/19:55:19
Here's the promised FPU detection code. I post it both in original asm
and
DJGPP inline asm forms. Code (AFAIK) originally comes from Intel and it
worked on all computers I have tested it against. Note that it assumes
it's being run on at least 386. The code uses FPU opcodes but it DOES
NOT
require any FPU emulation.
DO NOT TRY TO COMPILE THE DJGPP CODE WITH ANY OF THE -O OPTIONS - AS
WILL
COMPLAIN ABOUT UNRECOGNIZED 386 OPCODES.
--------------- cut here ------------
======== FPU.C =======
/* This is an official Intel FPU detection code converted to DJGPP
inline asm.
Note that this code assumes it is being run on at least i386.
On 486 and higher the code returns 1.
*/
int getFPU()
{
unsigned short fpu_status;
int fpu_type;
/*******************************************************************
; This procedure determines the type of FPU in a system
; and sets the fpu_type variable with the appropriate
; value.
; All registers are used by this procedure, none are preserved.
; Coprocessor check
; The algorithm is to determine whether the floating-point
; status and control words can be written to. If not, no
; coprocessor exists. If the status and control words can be
; written to, the correct coprocessor is then determined
; depending on the processor id. The Intel386 CPU can
; work with either an Intel287 NDP or an Intel387 NDP.
; The infinity of the coprocessor must be
; checked to determine the correct coprocessor id.
*********************************************************************/
asm("fninit \n" /* reset FP status word */
"movw $0x5a5ah, %0 \n" /* initialize temp word to */
" \n" /* non-zero value */
"fnstsw %0 \n" /* save FP status word */
"movw %0, %%ax \n" /* check FP status word */
"cmpb $0, %%al \n" /* see if correct status with */
" \n" /* written */
"movw $0, %0 \n" /* no fpu present */
"jne 0f \n"
"/* check_control_word: */ \n"
"fnstcw %0 \n" /* save FP control word */
"mov %0, %%ax \n" /* check FP control word */
"andw $0x103f, %%ax \n" /* see if selected parts */
" \n" /* looks OK */
"cmpw $0x3F, %%ax \n" /* check that 1's & 0's */
" \n" /* correctly read */
"movl $0, %1 \n"
"jne 0f \n"
"movl $1, %1 \n"
"/*\n"
" 80287/80387 check for the Intel386 CPU \n"
"\n"
"check_infinity: */\n"
"fld1 \n" /* must use default control from
FNINIT */
"fldz \n" /* form infinity */
"fdiv \n" /* 8087 and Intel287 NDP say +inf =
-inf */
"fld %%st \n" /* form negative infinity */
"fchs \n" /* Intel387 NDP says +inf <> -inf */
"fcompp \n" /* see if they are the same and
remove them */
"fstsw %0 \n" /* look at status from FCOMPP */
"movw %0, %%ax \n"
"movl $2, %1 \n" /* store Intel287 NDP for fpu type
*/
"sahf \n" /* see if infinities matched */
"jz 0f \n" /* jump if 8087 or Intel287 is
present */
"movl $3, %1 \n" /* store Intel387 NDP for fpu type
*/
"0: \n"
: "=g" (fpu_status),
"=g" (fpu_type));
return fpu_type;
}
======= FPU.ASM =======
.MODEL SMALL
.DATA
fp_status dw ?
fpu_type dw ?
cpu_type dw ?
.CODE
get_fpuid proc
;
; This procedure determines the type of FPU in a system
; and sets the fpu_type variable with the appropriate
; value.
; All registers are used by this procedure, none are preserved.
; Coprocessor check
; The algorithm is to determine whether the floating-point
; status and control words can be written to. If not, no
; coprocessor exists. If the status and control words can be
; written to, the correct coprocessor is then determined
; depending on the processor id. The Intel386 CPU can
; work with either an Intel287 NDP or an Intel387 NDP.
; The infinity of the coprocessor must be
; checked to determine the correct coprocessor id.
fninit ; reset FP status word
mov fp_status, 5a5ah; initialize temp word to
; non-zero value
fnstsw fp_status ; save FP status word
mov ax, fp_status ; check FP status word
cmp al, 0 ; see if correct status with
; written
mov fpu_type, 0 ; no fpu present
jne end_get_fpuid
check_control_word:
fnstcw fp_status ; save FP control word
mov ax, fp_status ; check FP control word
and ax, 103fh ; see if selected parts
; looks OK
cmp ax, 3fh ; check that 1's & 0's
; correctly read
mov fpu_type, 0
jne end_get_fpuid
mov fpu_type, 1
;
; 80287/80387 check for the Intel386 CPU
;
check_infinity:
cmp cpu_type, 3
jne end_get_fpuid
fld1 ; must use default control from FNINIT
fldz ; form infinity
fdiv ; 8087 and Intel287 NDP say +inf = -inf
fld st ; form negative infinity
fchs ; Intel387 NDP says +inf <> -inf
fcompp ; see if they are the same and remove
them
fstsw fp_status ; look at status from FCOMPP
mov ax, fp_status
mov fpu_type, 2 ; store Intel287 NDP for fpu type
sahf ; see if infinities matched
jz end_get_fpuid ; jump if 8087 or Intel287 is present
mov fpu_type, 3 ; store Intel387 NDP for fpu type
end_get_fpuid:
ret
get_fpuid endp
end
------------ cut here --------------
--
============================================================================
She nervously undressed in the dancing beams of the Fidra lighthouse
Giving it all away before it's too late. She'll let her lover's tongue
move in a warm wet circle, giving it all away and showing no shame.
She'll take her mother's kiss on her first broken heart, a warm wet
circle,
she'll realise that she plays her part in a warm wet circle...
=======================http://ananke.amu.edu.pl/~grendel====================
- Raw text -