Message-ID: <326FFC7C.15D1@ananke.amu.edu.pl> Date: Fri, 25 Oct 1996 01:32:13 +0200 From: Mark Habersack Reply-To: grendel AT ananke DOT amu DOT edu DOT pl Organization: home, sweet home MIME-Version: 1.0 To: "John M. Aldrich" CC: djgpp AT delorie DOT com Subject: FPU detection code Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit 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====================