community.borland.com

Article #15599: Trapping 8087 floating point exceptions in Pascal.

 Technical Information Database

TI599D.txt   Trapping 8087 floating point exceptions in Pascal.
Category   :General Programming
Platform    :All
Product    :Pascal  All

Description:
(*
This unit allows you to selectively handle floating point
errors - such a operations on NANs or infinity numbers - 
generated by the 8087 numeric coprocessor or emulation.  
This unit basically implements Pascal versions of C's 
_control87() and _stat87() functions and offers startup
code for a user-defined int75h handler.  For complete 
documentation on all of the constants in this unit, you
should reference either the C documentation on _control87(),
_stat87(), or signal(), or reference a 8087 programmer's guide.
*) 


unit Except87;

{
  NOTES: This unit is intended only for use on machines with an
         80286 processor or higher.

         If you intend to hook interrupt 75h while using this unit,
         you should call Int75Startup as the first line in your
         interrupt handler or very, very bad things will happen.
}

{$IfNDef Windows}

{$N+,E+}

{$Else}

{$N+}

{$EndIf}

interface

const
  { 387 Status Word format }
  SW_INVALID      = $0001;  { Invalid operation            }
  SW_DENORMAL     = $0002;  { Denormalized operand         }
  SW_ZERODIVIDE   = $0004;  { Zero divide                  }
  SW_OVERFLOW     = $0008;  { Overflow                     }
  SW_UNDERFLOW    = $0010;  { Underflow                    }
  SW_INEXACT      = $0020;  { Precision (Inexact result)   }
  SW_STACKFAULT   = $0040;  { Stack fault                  }

  { 387 Control Word format }
  MCW_EM              = $003f;  { interrupt Exception Masks}
      EM_INVALID      = $0001;  {   invalid                }
      EM_DENORMAL     = $0002;  {   denormal               }
      EM_ZERODIVIDE   = $0004;  {   zero divide            }
      EM_OVERFLOW     = $0008;  {   overflow               }
      EM_UNDERFLOW    = $0010;  {   underflow              }
      EM_INEXACT      = $0020;  {   inexact (precision)    }

  MCW_IC              = $1000;  { Infinity Control }
      IC_AFFINE       = $1000;  {   affine         }
      IC_PROJECTIVE   = $0000;  {   projective     }

  MCW_RC          = $0c00;  { Rounding Control     }
      RC_CHOP     = $0c00;  {   chop               }
      RC_UP       = $0800;  {   up                 }
      RC_DOWN     = $0400;  {   down               }
      RC_NEAR     = $0000;  {   near               }

  MCW_PC          = $0300;  { Precision Control    }
      PC_24       = $0000;  {    24 bits           }
      PC_53       = $0200;  {    53 bits           }
      PC_64       = $0300;  {    64 bits           }

function Control87(New, Mask: Word): Word;
function Status87: Word;
procedure Int75Startup; far;

implementation

procedure Int75Startup; assembler;
asm   { this is the entry code for your int 75 handler }
  xor al,   al                  { Clear BUSY latch}
  out 0F0h, al
  mov al,   20H                 { End-of-interrupt}
  out 0A0h, al
  out 20h,  al
end;

function Control87(New, Mask: Word): Word; assembler;
var
  Control: Word;
asm
  fstcw    Control
  mov  ax, New
  mov  bx, Mask
  and  ax, bx
  not  bx
  fwait
  mov  dx, Control
  and  dx, bx
  mov  Control, ax
  fldcw    Control
  xchg ax, dx
end;

function Status87: Word; assembler;
var
  Status: Word;
asm
  fstsw   Status
  fwait
  mov ax, Status
  and ax, SW_INVALID+SW_ZERODIVIDE+SW_OVERFLOW+SW_UNDERFLOW+SW_INEXACT
end;

end.

(********  This is a test program for the Except87 unit *******)

program TestFP;

{$N+}

uses Except87, DOS;

var
  f: single;
  p: pointer;
  i: word;

procedure Int75Handler; interrupt;
begin
  Int75Startup;
  i := 1;
end;

begin
  i := 0;
  Control87(0, MCW_EM);
  GetIntVec($75, p);
  SetIntVec($75, 
Int75Handler);
  f := 99999999999.99;
  f := f / 0.0;
  writeln('Coprocessor status: ', status87);
  SetIntVec($75, p);
  writeln('Did int75 fire?: ', i);
end.

Reference:


7/16/98 4:33:48 PM
 

Last Modified: 01-SEP-99