Browse Source

+ i8086 FPU detection code updated to also identify the FPU type (8087/287/387+)
and initialize the Test8087 global variable.

git-svn-id: trunk@26200 -

nickysn 11 years ago
parent
commit
180ddf2ddd
3 changed files with 44 additions and 7 deletions
  1. 39 4
      rtl/i8086/i8086.inc
  2. 3 2
      rtl/inc/systemh.inc
  3. 2 1
      rtl/msdos/system.pp

+ 39 - 4
rtl/i8086/i8086.inc

@@ -216,17 +216,52 @@ const
   fpucw : word = $1300 or FPU_StackUnderflow or FPU_Underflow or FPU_Denormal;
   }
 
-{ returns true if FPU is present }
-function DetectFPU: boolean;
+{ Detects the FPU and initializes the Test8087 variable:
+  0 = NO FPU
+  1 = 8087
+  2 = 80287
+  3 = 80387+ }
+procedure DetectFPU;
   var
     localfpucw: word;
   begin
     asm
+      xor bx, bx  { initialization, 0=NO FPU }
+
+      { FPU presence detection }
       fninit
       mov byte [localfpucw + 1], 0
+      nop
       fnstcw localfpucw
-    end;
-    DetectFPU:=(localfpucw and $FF00)=$0300;
+      cmp byte [localfpucw + 1], 3
+      jne @@Done  { No FPU? }
+      inc bx
+
+      { FPU found; now test if it's a 8087 }
+      and byte [localfpucw], $7F  { clear the interrupt enable mask (IEM) }
+      fldcw localfpucw
+      fdisi                       { try to set the interrupt enable mask }
+      fstcw localfpucw
+      test byte [localfpucw], $80 { IEM set? }
+      jnz @@Done  { if yes, we have an 8087 }
+      inc bx
+
+      { we have a 287+; now test if it's a 80287 }
+      finit
+      fld1
+      fldz
+      fdiv                        { calculate 1/0 }
+      fld st                      { copy the value }
+      fchs                        { change the sign }
+      fcompp  { compare. if the FPU distinguishes +inf from -inf, it's a 387+ }
+      fstsw localfpucw
+      mov ah, byte [localfpucw + 1]
+      sahf
+      je @@Done
+      inc bx  { 387+ }
+@@Done:
+      mov Test8087, bl
+    end ['AX','BX'];
   end;
 
 {$define FPC_SYSTEM_HAS_SYSINITFPU}

+ 3 - 2
rtl/inc/systemh.inc

@@ -605,8 +605,9 @@ const
   { will be detected at startup }
   { 0=8086/8088/80186/80188/NEC V20/NEC V30, 1=80286, 2=80386 or newer }
   Test8086 : byte = 0; public name '__Test8086';
-  { Always 387 or newer. Emulated if needed. }
-  Test8087 : byte = 3;
+  { will be detected at startup }
+  { 0=NO FPU, 1=8087, 2=80287, 3=80387 or newer }
+  Test8087 : byte = 0;
   { will be detected at startup }
   has_sse_support : boolean = false;
   has_mmx_support : boolean = false;

+ 2 - 1
rtl/msdos/system.pp

@@ -340,7 +340,8 @@ begin
   StackBottom := __stkbottom;
   StackLength := __stktop - __stkbottom;
   InstallInterruptHandlers;
-  if DetectFPU then
+  DetectFPU;
+  if Test8087>0 then
     SysInitFPU;
   { To be set if this is a GUI or console application }
   IsConsole := TRUE;