mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-08 01:08:07 +02:00
* improved software floating point exception handling in the rtl
git-svn-id: trunk@43163 -
This commit is contained in:
parent
29bdbdba95
commit
c189af0e3d
@ -83,9 +83,9 @@ const
|
||||
FPSCR_UFC = 1 shl 3;
|
||||
FPSCR_IXC = 1 shl 4;
|
||||
FPSCR_IDC = 1 shl 7;
|
||||
FPSCR_EXCEPTIONS = FPSCR_IOC or FPSCR_DZC or FPSCR_OFC or FPSCR_UFC or FPSCR_IXC or FPSCR_IDC;
|
||||
|
||||
|
||||
procedure fpc_throwfpuexception;[public,alias:'FPC_THROWFPUEXCEPTION'];
|
||||
procedure RaisePendingExceptions;
|
||||
var
|
||||
fpscr : longint;
|
||||
f: TFPUException;
|
||||
@ -112,6 +112,34 @@ procedure fpc_throwfpuexception;[public,alias:'FPC_THROWFPUEXCEPTION'];
|
||||
end;
|
||||
|
||||
|
||||
procedure fpc_throwfpuexception;[public,alias:'FPC_THROWFPUEXCEPTION'];
|
||||
var
|
||||
fpscr : dword;
|
||||
f: TFPUException;
|
||||
begin
|
||||
{ at this point, we know already, that an exception will be risen }
|
||||
fpscr:=getfpscr;
|
||||
|
||||
{ check, if the exception is masked, as ARM without hardware exceptions have no masking functionality,
|
||||
we use the software mask }
|
||||
if ((fpscr and FPSCR_DZC) <> 0) and (exZeroDivide in softfloat_exception_mask) then
|
||||
fpscr:=fpscr and not(FPSCR_DZC);
|
||||
if ((fpscr and FPSCR_OFC) <> 0) and (exOverflow in softfloat_exception_mask) then
|
||||
fpscr:=fpscr and not(FPSCR_OFC);
|
||||
if ((fpscr and FPSCR_UFC) <> 0) and (exUnderflow in softfloat_exception_mask) then
|
||||
fpscr:=fpscr and not(FPSCR_UFC);
|
||||
if ((fpscr and FPSCR_IOC) <> 0) and (exInvalidOp in softfloat_exception_mask) then
|
||||
fpscr:=fpscr and not(FPSCR_IOC);
|
||||
if ((fpscr and FPSCR_IXC) <> 0) and (exPrecision in softfloat_exception_mask) then
|
||||
fpscr:=fpscr and not(FPSCR_IXC);
|
||||
if ((fpscr and FPSCR_IDC) <> 0) and (exDenormalized in softfloat_exception_mask) then
|
||||
fpscr:=fpscr and not(FPSCR_IDC);
|
||||
setfpscr(fpscr);
|
||||
if (fpscr and FPSCR_EXCEPTIONS)<>0 then
|
||||
RaisePendingExceptions;
|
||||
end;
|
||||
|
||||
|
||||
Procedure SysInitFPU;{$ifdef SYSTEMINLINE}inline;{$endif}
|
||||
begin
|
||||
{ Enable FPU exceptions, but disable INEXACT, UNDERFLOW, DENORMAL }
|
||||
@ -133,7 +161,18 @@ begin
|
||||
{$endif}
|
||||
fmxr fpscr,r0
|
||||
end;
|
||||
softfloat_exception_mask:=[float_flag_underflow,float_flag_inexact,float_flag_denormal];
|
||||
softfloat_exception_flags:=[];
|
||||
end;
|
||||
|
||||
{$define FPC_SYSTEM_HAS_SYSRESETFPU}
|
||||
Procedure SysResetFPU;{$ifdef SYSTEMINLINE}inline;{$endif}
|
||||
begin
|
||||
softfloat_exception_flags:=[];
|
||||
setfpscr(getfpscr and not(FPSCR_EXCEPTIONS));
|
||||
end;
|
||||
|
||||
|
||||
{$endif}
|
||||
{$endif}
|
||||
|
||||
|
@ -250,7 +250,12 @@ function VFPCw2ExceptionMask(cw: dword): TFPUExceptionMask;
|
||||
|
||||
function GetExceptionMask: TFPUExceptionMask;
|
||||
begin
|
||||
Result:=VFPCw2ExceptionMask(VFP_GetCW);
|
||||
{ some ARM CPUs ignore writing to the hardware mask and just return 0, so we need to return
|
||||
the softfloat mask which should be in sync with the hard one }
|
||||
if VFP_GetCW=0 then
|
||||
Result:=softfloat_exception_mask
|
||||
else
|
||||
Result:=VFPCw2ExceptionMask(VFP_GetCW);
|
||||
end;
|
||||
|
||||
|
||||
@ -290,6 +295,7 @@ procedure ClearExceptions(RaisePending: Boolean =true);
|
||||
begin
|
||||
{ RaisePending has no effect on ARM, it always raises them at the correct location }
|
||||
VFP_SetCW(VFP_GetCW and (not _VFP_EXCEPTIONS_PENDING_MASK));
|
||||
softfloat_exception_flags:=[];
|
||||
end;
|
||||
|
||||
{$else FPUARM_HAS_VFP_EXTENSION}
|
||||
|
@ -19,6 +19,7 @@
|
||||
Procedure SysInitFPU;{$ifdef SYSTEMINLINE}inline;{$endif}
|
||||
begin
|
||||
softfloat_exception_mask:=[float_flag_underflow,float_flag_inexact,float_flag_denormal];
|
||||
softfloat_exception_flags:=[];
|
||||
end;
|
||||
|
||||
|
||||
|
@ -134,20 +134,21 @@ Begin
|
||||
pflags := @softfloat_exception_flags;
|
||||
pflags^:=pflags^ + i;
|
||||
unmasked_flags := pflags^ - softfloat_exception_mask;
|
||||
{ before we raise the exception, we mark it as handled,
|
||||
this behaviour is similiar to the hardware handler in SignalToRunerror }
|
||||
SysResetFPU;
|
||||
if (float_flag_invalid in unmasked_flags) then
|
||||
HandleError(207)
|
||||
else
|
||||
if (float_flag_divbyzero in unmasked_flags) then
|
||||
else if (float_flag_divbyzero in unmasked_flags) then
|
||||
HandleError(200)
|
||||
else
|
||||
if (float_flag_overflow in unmasked_flags) then
|
||||
else if (float_flag_overflow in unmasked_flags) then
|
||||
HandleError(205)
|
||||
else
|
||||
if (float_flag_underflow in unmasked_flags) then
|
||||
else if (float_flag_underflow in unmasked_flags) then
|
||||
HandleError(206)
|
||||
else
|
||||
if (float_flag_inexact in unmasked_flags) then
|
||||
HandleError(207);
|
||||
else if (float_flag_inexact in unmasked_flags) then
|
||||
HandleError(207)
|
||||
else if (float_flag_denormal in unmasked_flags) then
|
||||
HandleError(216);
|
||||
end;
|
||||
|
||||
|
||||
|
@ -70,6 +70,7 @@ begin
|
||||
begin
|
||||
{ don't know how to find the different causes, maybe via xer? }
|
||||
res := 207;
|
||||
SysResetFPU;
|
||||
end;
|
||||
SIGILL:
|
||||
{$ifdef FPC_SYSTEM_FPC_MOVE}
|
||||
|
Loading…
Reference in New Issue
Block a user