www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1996/10/24/19:55:19

Message-ID: <326FFC7C.15D1@ananke.amu.edu.pl>
Date: Fri, 25 Oct 1996 01:32:13 +0200
From: Mark Habersack <grendel AT ananke DOT amu DOT edu DOT pl>
Reply-To: grendel AT ananke DOT amu DOT edu DOT pl
Organization: home, sweet home
MIME-Version: 1.0
To: "John M. Aldrich" <fighteer AT cs DOT com>
CC: djgpp AT delorie DOT com
Subject: FPU detection code

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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019