summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorflorian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2>2018-08-19 10:55:41 +0000
committerflorian <florian@3ad0048d-3df7-0310-abae-a5850022a9f2>2018-08-19 10:55:41 +0000
commit7e3e75f1ddd29aab06e7efbeef4bb7320d752643 (patch)
treed175ab519ce0aef5b5575a2cd0b828f9b05a4c3b
parent630c20e6a562086875ebd769e60bf19cc65191cb (diff)
downloadfpc-7e3e75f1ddd29aab06e7efbeef4bb7320d752643.tar.gz
* fixed floating point exception masking support for RiscV64
git-svn-id: https://svn.freepascal.org/svn/fpc/branches/laksen@39638 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r--riscv_new/rtl/riscv64/mathu.inc105
-rw-r--r--riscv_new/rtl/riscv64/riscv64.inc70
2 files changed, 106 insertions, 69 deletions
diff --git a/riscv_new/rtl/riscv64/mathu.inc b/riscv_new/rtl/riscv64/mathu.inc
index 74743e0a6e..e76b595641 100644
--- a/riscv_new/rtl/riscv64/mathu.inc
+++ b/riscv_new/rtl/riscv64/mathu.inc
@@ -22,13 +22,15 @@ procedure setfpcr(val: dword); nostackframe; assembler;
end;
-function getfpsr: dword; nostackframe; assembler;
+function getfflags: dword; nostackframe; assembler;
asm
+ frflags a0
end;
-procedure setfpsr(val: dword); nostackframe; assembler;
+procedure setfflags(flags : dword); nostackframe; assembler;
asm
+ fsflags a0
end;
@@ -61,91 +63,56 @@ function SetPrecisionMode(const Precision: TFPUPrecisionMode): TFPUPrecisionMode
result:=pmDouble;
end;
-
const
- fpu_ioe = 1 shl 8;
- fpu_dze = 1 shl 9;
- fpu_ofe = 1 shl 10;
- fpu_ufe = 1 shl 11;
- fpu_ixe = 1 shl 12;
- fpu_ide = 1 shl 15;
- fpu_exception_mask = fpu_ioe or fpu_dze or fpu_ofe or fpu_ufe or fpu_ixe or fpu_ide;
- fpu_exception_mask_to_status_mask_shift = 8;
+ fpu_nx = 1 shl 0;
+ fpu_uf = 1 shl 1;
+ fpu_of = 1 shl 2;
+ fpu_dz = 1 shl 3;
+ fpu_nv = 1 shl 4;
function GetExceptionMask: TFPUExceptionMask;
- var
- fpcr: dword;
begin
- fpcr:=getfpcr;
- result:=[];
- if ((fpcr and fpu_ioe)=0) then
- result := result+[exInvalidOp];
- if ((fpcr and fpu_ofe)=0) then
- result := result+[exOverflow];
- if ((fpcr and fpu_ufe)=0) then
- result := result+[exUnderflow];
- if ((fpcr and fpu_dze)=0) then
- result := result+[exZeroDivide];
- if ((fpcr and fpu_ixe)=0) then
- result := result+[exPrecision];
- if ((fpcr and fpu_ide)=0) then
- result := result+[exDenormalized];
+ Result:=softfloat_exception_mask;
end;
function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
- var
- newfpcr: dword;
begin
- softfloat_exception_mask:=mask;
- newfpcr:=fpu_exception_mask;
- if exInvalidOp in Mask then
- newfpcr:=newfpcr and not(fpu_ioe);
- if exOverflow in Mask then
- newfpcr:=newfpcr and not(fpu_ofe);
- if exUnderflow in Mask then
- newfpcr:=newfpcr and not(fpu_ufe);
- if exZeroDivide in Mask then
- newfpcr:=newfpcr and not(fpu_dze);
- if exPrecision in Mask then
- newfpcr:=newfpcr and not(fpu_ixe);
- if exDenormalized in Mask then
- newfpcr:=newfpcr and not(fpu_ide);
+ Result:=softfloat_exception_mask;
{ clear "exception happened" flags }
ClearExceptions(false);
- { set new exception mask }
- setfpcr((getfpcr and not(fpu_exception_mask)) or newfpcr);
- { unsupported mask bits will remain 0 -> read exception mask again }
- result:=GetExceptionMask;
- softfloat_exception_mask:=result;
+ softfloat_exception_mask:=Mask;
end;
-procedure ClearExceptions(RaisePending: Boolean);
+procedure RaisePendingExceptions;
var
- fpsr: dword;
+ fflags : dword;
f: TFPUException;
begin
- fpsr:=getfpsr;
+ fflags:=getfflags;
+ if (fflags and fpu_dz) <> 0 then
+ float_raise(exZeroDivide);
+ if (fflags and fpu_of) <> 0 then
+ float_raise(exOverflow);
+ if (fflags and fpu_uf) <> 0 then
+ float_raise(exUnderflow);
+ if (fflags and fpu_nv) <> 0 then
+ float_raise(exInvalidOp);
+ if (fflags and fpu_nx) <> 0 then
+ float_raise(exPrecision);
+ { now the soft float exceptions }
+ for f in softfloat_exception_flags do
+ float_raise(f);
+ end;
+
+
+procedure ClearExceptions(RaisePending: Boolean);
+ begin
if raisepending then
- begin
- if (fpsr and (fpu_dze shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
- float_raise(exZeroDivide);
- if (fpsr and (fpu_ofe shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
- float_raise(exOverflow);
- if (fpsr and (fpu_ufe shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
- float_raise(exUnderflow);
- if (fpsr and (fpu_ioe shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
- float_raise(exInvalidOp);
- if (fpsr and (fpu_ixe shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
- float_raise(exPrecision);
- if (fpsr and (fpu_ide shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
- float_raise(exDenormalized);
- { now the soft float exceptions }
- for f in softfloat_exception_flags do
- float_raise(f);
- end;
+ RaisePendingExceptions;
softfloat_exception_flags:=[];
- setfpsr(fpsr and not(fpu_exception_mask shr fpu_exception_mask_to_status_mask_shift));
+ setfflags(0);
end;
+
diff --git a/riscv_new/rtl/riscv64/riscv64.inc b/riscv_new/rtl/riscv64/riscv64.inc
index 886ed4fc1b..cac65a5b85 100644
--- a/riscv_new/rtl/riscv64/riscv64.inc
+++ b/riscv_new/rtl/riscv64/riscv64.inc
@@ -19,6 +19,76 @@ procedure fpc_cpuinit;{$ifdef SYSTEMINLINE}inline;{$endif}
begin
end;
+{****************************************************************************
+ fpu exception related stuff
+****************************************************************************}
+
+const
+ fpu_nx = 1 shl 0;
+ fpu_uf = 1 shl 1;
+ fpu_of = 1 shl 2;
+ fpu_dz = 1 shl 3;
+ fpu_nv = 1 shl 4;
+
+function getfflags: dword; nostackframe; assembler;
+ asm
+ frflags a0
+ end;
+
+
+procedure setfflags(flags : dword); nostackframe; assembler;
+ asm
+ fsflags a0
+ end;
+
+
+procedure RaisePendingExceptions;
+ var
+ fflags : dword;
+ f: TFPUException;
+ begin
+ fflags:=getfflags;
+ if (fflags and fpu_dz) <> 0 then
+ float_raise(exZeroDivide);
+ if (fflags and fpu_of) <> 0 then
+ float_raise(exOverflow);
+ if (fflags and fpu_uf) <> 0 then
+ float_raise(exUnderflow);
+ if (fflags and fpu_nv) <> 0 then
+ float_raise(exInvalidOp);
+ if (fflags and fpu_nx) <> 0 then
+ float_raise(exPrecision);
+ { now the soft float exceptions }
+ for f in softfloat_exception_flags do
+ float_raise(f);
+ end;
+
+
+procedure fpc_throwfpuexception;[public,alias:'FPC_THROWFPUEXCEPTION'];
+ var
+ fflags : dword;
+ begin
+ fflags:=getfflags;
+ { check, if the exception is masked }
+ if ((fflags and fpu_dz) <> 0) and (exZeroDivide in softfloat_exception_mask) then
+ fflags:=fflags and not(fpu_dz);
+ if ((fflags and fpu_of) <> 0) and (exOverflow in softfloat_exception_mask) then
+ fflags:=fflags and not(fpu_of);
+ if ((fflags and fpu_uf) <> 0) and (exUnderflow in softfloat_exception_mask) then
+ fflags:=fflags and not(fpu_uf);
+ if ((fflags and fpu_nv) <> 0) and (exInvalidOp in softfloat_exception_mask) then
+ fflags:=fflags and not(fpu_nv);
+ if ((fflags and fpu_nx) <> 0) and (exPrecision in softfloat_exception_mask) then
+ fflags:=fflags and not(fpu_nx);
+ setfflags(fflags);
+ if fflags<>0 then
+ RaisePendingExceptions;
+ end;
+
+
+{****************************************************************************
+ stack frame related stuff
+****************************************************************************}
{$IFNDEF INTERNAL_BACKTRACE}
{$define FPC_SYSTEM_HAS_GET_FRAME}