* fpa exception masking fixed

git-svn-id: trunk@6026 -
This commit is contained in:
florian 2007-01-17 15:52:36 +00:00
parent 2fabc692fa
commit 075011a2a5
2 changed files with 186 additions and 8 deletions

View File

@ -24,15 +24,15 @@ const
_EM_OVERFLOW = $00000004;
_EM_UNDERFLOW = $00000002;
_EM_INEXACT = $00000001;
_IC_AFFINE = $00040000;
_IC_PROJECTIVE = $00000000;
_RC_CHOP = $00000300;
_RC_UP = $00000200;
_RC_DOWN = $00000100;
_RC_NEAR = $00000000;
_PC_24 = $00020000;
_PC_53 = $00010000;
_PC_64 = $00000000;
@ -132,4 +132,187 @@ procedure ClearExceptions(RaisePending: Boolean =true);
begin
end;
{$else wince}
{*****************************************************************************
FPA code
*****************************************************************************}
{
Docs from uclib
* We have a slight terminology confusion here. On the ARM, the register
* we're interested in is actually the FPU status word - the FPU control
* word is something different (which is implementation-defined and only
* accessible from supervisor mode.)
*
* The FPSR looks like this:
*
* 31-24 23-16 15-8 7-0
* | system ID | trap enable | system control | exception flags |
*
* We ignore the system ID bits; for interest's sake they are:
*
* 0000 "old" FPE
* 1000 FPPC hardware
* 0001 FPE 400
* 1001 FPA hardware
*
* The trap enable and exception flags are both structured like this:
*
* 7 - 5 4 3 2 1 0
* | reserved | INX | UFL | OFL | DVZ | IVO |
*
* where a `1' bit in the enable byte means that the trap can occur, and
* a `1' bit in the flags byte means the exception has occurred.
*
* The exceptions are:
*
* IVO - invalid operation
* DVZ - divide by zero
* OFL - overflow
* UFL - underflow
* INX - inexact (do not use; implementations differ)
*
* The system control byte looks like this:
*
* 7-5 4 3 2 1 0
* | reserved | AC | EP | SO | NE | ND |
*
* where the bits mean
*
* ND - no denormalised numbers (force them all to zero)
* NE - enable NaN exceptions
* SO - synchronous operation
* EP - use expanded packed-decimal format
* AC - use alternate definition for C flag on compare operations
*/
/* masking of interrupts */
#define _FPU_MASK_IM 0x00010000 /* invalid operation */
#define _FPU_MASK_ZM 0x00020000 /* divide by zero */
#define _FPU_MASK_OM 0x00040000 /* overflow */
#define _FPU_MASK_UM 0x00080000 /* underflow */
#define _FPU_MASK_PM 0x00100000 /* inexact */
#define _FPU_MASK_DM 0x00000000 /* denormalized operation */
/* The system id bytes cannot be changed.
Only the bottom 5 bits in the trap enable byte can be changed.
Only the bottom 5 bits in the system control byte can be changed.
Only the bottom 5 bits in the exception flags are used.
The exception flags are set by the fpu, but can be zeroed by the user. */
#define _FPU_RESERVED 0xffe0e0e0 /* These bits are reserved. */
/* The fdlibm code requires strict IEEE double precision arithmetic,
no interrupts for exceptions, rounding to nearest. Changing the
rounding mode will break long double I/O. Turn on the AC bit,
the compiler generates code that assumes it is on. */
#define _FPU_DEFAULT 0x00001000 /* Default value. */
#define _FPU_IEEE 0x001f1000 /* Default + exceptions enabled. */
}
const
_FPU_MASK_IM = $00010000; { invalid operation }
_FPU_MASK_ZM = $00020000; { divide by zero }
_FPU_MASK_OM = $00040000; { overflow }
_FPU_MASK_UM = $00080000; { underflow }
_FPU_MASK_PM = $00100000; { inexact }
_FPU_MASK_DM = $00000000; { denormalized operation }
_FPU_MASK_ALL = $001f0000; { mask for all flags }
function FPU_GetCW : dword; nostackframe; assembler;
asm
rfs r0
end;
procedure FPU_SetCW(cw : dword); nostackframe; assembler;
asm
wfs r0
end;
function GetRoundMode: TFPURoundingMode;
begin
{ does not apply }
end;
function SetRoundMode(const RoundMode: TFPURoundingMode): TFPURoundingMode;
begin
{ does not apply }
end;
function GetPrecisionMode: TFPUPrecisionMode;
begin
{ does not apply }
end;
function SetPrecisionMode(const Precision: TFPUPrecisionMode): TFPUPrecisionMode;
begin
{ does not apply }
end;
function GetExceptionMask: TFPUExceptionMask;
var
cw : dword;
begin
Result:=[];
cw:=FPU_GetCW;
if (cw and _FPU_MASK_IM)<>0 then
include(Result,exInvalidOp);
if (cw and _FPU_MASK_DM)<>0 then
include(Result,exDenormalized);
if (cw and _FPU_MASK_ZM)<>0 then
include(Result,exZeroDivide);
if (cw and _FPU_MASK_OM)<>0 then
include(Result,exOverflow);
if (cw and _FPU_MASK_UM)<>0 then
include(Result,exUnderflow);
if (cw and _FPU_MASK_PM)<>0 then
include(Result,exPrecision);
end;
function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
var
cw : dword;
begin
cw:=FPU_GetCW and not(_FPU_MASK_ALL);
if exInvalidOp in Mask then
cw:=cw or _FPU_MASK_IM;
if exDenormalized in Mask then
cw:=cw or _FPU_MASK_DM;
if exZeroDivide in Mask then
cw:=cw or _FPU_MASK_ZM;
if exOverflow in Mask then
cw:=cw or _FPU_MASK_OM;
if exUnderflow in Mask then
cw:=cw or _FPU_MASK_UM;
if exPrecision in Mask then
cw:=cw or _FPU_MASK_PM;
FPU_SetCW(cw);
end;
procedure ClearExceptions(RaisePending: Boolean =true);
begin
end;
{$endif wince}

View File

@ -11,9 +11,6 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
**********************************************************************}
{$ifdef wince}
type
TFPURoundingMode = (rmNearest, rmDown, rmUp, rmTruncate);
TFPUPrecisionMode = (pmSingle, pmReserved, pmDouble, pmExtended);
@ -28,5 +25,3 @@ function SetPrecisionMode(const Precision: TFPUPrecisionMode): TFPUPrecisionMode
function GetExceptionMask: TFPUExceptionMask;
function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
procedure ClearExceptions(RaisePending: Boolean =true);
{$endif}