Filter:   InfoImg
download Jcl8087.pas
Language: Delphi
LOC: 138
Project Info
XVCL
Server: SourceForge
Type: cvs
...rge\x\xvcl\xvcl\JCL\Source\
   _source_.dof
   DJCL50.dpk
   JCL.INC
   Jcl8087.pas
   JclAppInst.pas
   JclBase.pas
   JclCOM.pas
   JclComplex.pas
   JclCounter.pas
   JclDateTime.pas
   JclDebug.pas
   JclExcel.pas
   jclexpreval.pas
   JclFileUtils.pas
   JclGraphics.pas
   JclGraphUtils.pas
   JclHookExcept.pas
   JclIniFiles.pas
   JclLANMan.pas
   JclLocales.pas
   JclLogic.pas
   JclMapi.pas
   JclMath.pas
   JclMime.pas
   JclMiscel.pas
   JclMultimedia.pas
   JclNTFS.pas
   JclPeImage.pas
   JclPrint.pas
   JclRegistry.pas
   JclResources.pas
   JclRTF.pas
   JclRTTI.pas
   JclSecurity.pas
   JclShell.pas
   JclSscanf.pas
   JclStatistics.pas
   JclStrHashMap.pas
   JclStrings.pas
   JclSynch.pas
   JclSysInfo.pas
   JclSysUtils.pas
   JclUnicode.pas
   JclUnicode.rc
   JclUnitConv.pas
   JclWin32.pas
   LM.pas

{******************************************************************************}
{                                                                              }
{ Project JEDI Code Library (JCL)                                              }
{                                                                              }
{ The contents of this file are subject to the Mozilla Public License Version  }
{ 1.1 (the "License"); you may not use this file except in compliance with the }
{ License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ }
{                                                                              }
{ Software distributed under the License is distributed on an "AS IS" basis,   }
{ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for }
{ the specific language governing rights and limitations under the License.    }
{                                                                              }
{ The Original Code is Jcl8087.pas.                                            }
{                                                                              }
{ The Initial Developer of the Original Code is documented in the accompanying }
{ help file JCL.chm. Portions created by these individuals are Copyright (C)   }
{ of these individuals.                                                        }
{                                                                              }
{******************************************************************************}
{                                                                              }
{ This unit contains various routine for manipulating the math coprocessor.    }
{ This includes such things as querying and setting the rounding precision of  }
{ floating point operations and retrieving the coprocessor's status word.      }
{                                                                              }
{ Unit owner: Marcel van Brakel                                                }
{ Last modified: January 29, 2001                                              }
{                                                                              }
{******************************************************************************}

unit Jcl8087;

{$I JCL.INC}

{$WEAKPACKAGEUNIT ON}

interface

type
  T8087Precision = (pcSingle, pcReserved, pcDouble, pcExtended);
  T8087Rounding = (rcNearestOrEven, rcDownInfinity, rcUpInfinity, rcChopOrTruncate);
  T8087Infinity = (icProjective, icAffine);
  T8087Exception = (emInvalidOp, emDenormalizedOperand, emZeroDivide, emOverflow,
    emUnderflow, emPrecision);
  T8087Exceptions = set of T8087Exception;

const
  All8087Exceptions = [Low(T8087Exception)..High(T8087Exception)];

function Get8087ControlWord: Word;
function Get8087Infinity: T8087Infinity;
function Get8087Precision: T8087Precision;
function Get8087Rounding: T8087Rounding;
function Get8087StatusWord(ClearExceptions: Boolean): Word;

function Set8087Infinity(const Infinity: T8087Infinity): T8087Infinity;
function Set8087Precision(const Precision: T8087Precision): T8087Precision;
function Set8087Rounding(const Rounding: T8087Rounding): T8087Rounding;
function Set8087ControlWord(const Control: Word): Word;

function ClearPending8087Exceptions: T8087Exceptions;
function GetPending8087Exceptions: T8087Exceptions;
function GetMasked8087Exceptions: T8087Exceptions;
function SetMasked8087Exceptions(Exceptions: T8087Exceptions;
  ClearBefore: Boolean {$IFDEF SUPPORTS_DEFAULTPARAMS} = True {$ENDIF}): T8087Exceptions;
function Mask8087Exceptions(Exceptions: T8087Exceptions): T8087Exceptions;
function Unmask8087Exceptions(Exceptions: T8087Exceptions;
  ClearBefore: Boolean {$IFDEF SUPPORTS_DEFAULTPARAMS} = True {$ENDIF}): T8087Exceptions;

implementation

const
  X87ExceptBits = $3F;

//------------------------------------------------------------------------------

function Get8087ControlWord: Word; assembler;
asm
        SUB     ESP, TYPE WORD
        FSTCW   [ESP]
        FWAIT
        POP AX
end;

//------------------------------------------------------------------------------

function Get8087Infinity: T8087Infinity;
begin
  Result := T8087Infinity((Get8087ControlWord and $1000) shr 12);
end;

//------------------------------------------------------------------------------

function Get8087Precision: T8087Precision;
begin
  Result := T8087Precision((Get8087ControlWord and $0300) shr 8);
end;

//------------------------------------------------------------------------------

function Get8087Rounding: T8087Rounding;
begin
  Result := T8087Rounding((Get8087ControlWord and $0C00) shr 10);
end;

//------------------------------------------------------------------------------

function Get8087StatusWord(ClearExceptions: Boolean): Word; assembler;
asm
        TEST    AX, AX                // if ClearExceptions then
        JE      @@NoClearExceptions
        FSTSW   AX                    //   get status word (clears exceptions)
        RET
@@NoClearExceptions:                  // else
        FNSTSW  AX                    //   get status word (without clearing exceptions)
end;

//------------------------------------------------------------------------------

function Set8087Infinity(const Infinity: T8087Infinity): T8087Infinity;
var
  CW: Word;
begin
  CW := Get8087ControlWord;
  Result := T8087Infinity((CW and $1000) shr 12);
  Set8087ControlWord((CW and $EFFF) or (Word(Infinity) shl 12));
end;

//------------------------------------------------------------------------------

function Set8087Precision(const Precision: T8087Precision): T8087Precision;
var
  CW: Word;
begin
  CW := Get8087ControlWord;
  Result := T8087Precision((CW and $0300) shr 8);
  Set8087ControlWord((CW and $FCFF) or (Word(Precision) shl 8));
end;

//------------------------------------------------------------------------------

function Set8087Rounding(const Rounding: T8087Rounding): T8087Rounding;
var
  CW: Word;
begin
  CW := Get8087ControlWord;
  Result := T8087Rounding((CW and $0C00) shr 10);
  Set8087ControlWord((CW and $F3FF) or (Word(Rounding) shl 10));
end;

//------------------------------------------------------------------------------

function Set8087ControlWord(const Control: Word): Word; assembler;
asm
        FNCLEX
        FSTCW   Default8087CW
        XCHG    Default8087CW, AX
        FLDCW   Default8087CW
end;

//------------------------------------------------------------------------------

function ClearPending8087Exceptions: T8087Exceptions;
asm
        FNSTSW  AX
        AND     AX, X87ExceptBits
        FNCLEX
end;

//------------------------------------------------------------------------------

function GetPending8087Exceptions: T8087Exceptions;
asm
        FNSTSW  AX
        AND     AX, X87ExceptBits
end;

//------------------------------------------------------------------------------

function GetMasked8087Exceptions: T8087Exceptions;
asm
        SUB     ESP, TYPE Word
        FSTCW   [ESP]
        FWAIT
        POP     AX
        AND     AX, X87ExceptBits
end;

//------------------------------------------------------------------------------

function SetMasked8087Exceptions(Exceptions: T8087Exceptions; ClearBefore: Boolean): T8087Exceptions;
asm
        TEST    DL, DL             // if ClearBefore then
        JZ      @1
        FNCLEX                     // clear pending exceptions
@1:
        FSTCW   Default8087CW
        FWAIT
        AND     AX, X87ExceptBits  // mask exception mask bits 0..5
        MOV     DX, Default8087CW
        AND     Default8087CW, NOT X87ExceptBits
        OR      Default8087CW, AX
        FLDCW   Default8087CW
        MOV     AX, DX
        AND     AX, X87ExceptBits
end;

//------------------------------------------------------------------------------

function Mask8087Exceptions(Exceptions: T8087Exceptions): T8087Exceptions;
begin
  Result := GetMasked8087Exceptions;
  Exceptions := Exceptions + Result;
  SetMasked8087Exceptions(Exceptions, False);
end;

//------------------------------------------------------------------------------

function Unmask8087Exceptions(Exceptions: T8087Exceptions; ClearBefore: Boolean): T8087Exceptions;
begin
  Result := GetMasked8087Exceptions;
  Exceptions := Result - Exceptions;
  SetMasked8087Exceptions(Exceptions, ClearBefore);
end;

end.