summaryrefslogtreecommitdiff
path: root/mips/rtl/mips/mathu.inc
diff options
context:
space:
mode:
Diffstat (limited to 'mips/rtl/mips/mathu.inc')
-rw-r--r--mips/rtl/mips/mathu.inc123
1 files changed, 81 insertions, 42 deletions
diff --git a/mips/rtl/mips/mathu.inc b/mips/rtl/mips/mathu.inc
index 9f3ffff15a..8b3063dfa6 100644
--- a/mips/rtl/mips/mathu.inc
+++ b/mips/rtl/mips/mathu.inc
@@ -13,8 +13,29 @@
**********************************************************************}
{ exported by the system unit }
-//!!!function get_fsr : dword;external name 'FPC_GETFSR';
-//!!!procedure set_fsr(fsr : dword);external name 'FPC_SETFSR';
+function get_fsr : dword;external name 'FPC_GETFSR';
+procedure set_fsr(fsr : dword);external name 'FPC_SETFSR';
+
+const
+ { FPU enable exception bits for FCSR register }
+ fpu_enable_inexact = $80;
+ fpu_enable_underflow = $100;
+ fpu_enable_overflow = $200;
+ fpu_enable_div_zero = $400;
+ fpu_enable_invalid = $800;
+ fpu_enable_mask = $F80;
+ default_fpu_enable = fpu_enable_div_zero or fpu_enable_invalid;
+
+ fpu_flags_mask = $7C;
+ fpu_cause_mask = $3F000;
+
+ { FPU rounding mask and values }
+ fpu_rounding_mask = $3;
+ fpu_rounding_nearest = 0;
+ fpu_rounding_towards_zero = 1;
+ fpu_rounding_plus_inf = 2;
+ fpu_rounding_minus_inf = 3;
+
function FPUExceptionMaskToSoftFloatMask(const Mask: TFPUExceptionMask): byte;
begin
@@ -35,22 +56,37 @@ end;
function GetRoundMode: TFPURoundingMode;
begin
-//!!! result:=TFPURoundingMode(get_fsr shr 30);
+ result:=TFPURoundingMode(get_fsr and 3);
end;
function SetRoundMode(const RoundMode: TFPURoundingMode): TFPURoundingMode;
+ var
+ fpu_round : longint;
begin
+
case (RoundMode) of
rmNearest :
- softfloat_rounding_mode := float_round_nearest_even;
+ begin
+ softfloat_rounding_mode := float_round_nearest_even;
+ fpu_round:=fpu_rounding_nearest;
+ end;
rmTruncate :
- softfloat_rounding_mode := float_round_to_zero;
- rmUp :
- softfloat_rounding_mode := float_round_up;
- rmDown :
- softfloat_rounding_mode := float_round_down;
- end;
-//!!! set_fsr((get_fsr and $3fffffff) or (dword(RoundMode) shl 30));
+ begin
+ softfloat_rounding_mode := float_round_to_zero;
+ fpu_round:=fpu_rounding_towards_zero;
+ end;
+ rmUp :
+ begin
+ softfloat_rounding_mode := float_round_up;
+ fpu_round:=fpu_rounding_plus_inf;
+ end;
+ rmDown :
+ begin
+ softfloat_rounding_mode := float_round_down;
+ fpu_round:=fpu_rounding_minus_inf;
+ end;
+ end;
+ set_fsr((get_fsr and not fpu_rounding_mask) or fpu_round);
//!!! result:=TFPURoundingMode(get_fsr shr 30);
end;
@@ -71,26 +107,26 @@ function GetExceptionMask: TFPUExceptionMask;
var
fsr : dword;
begin
-//!!! fsr:=get_fsr;
+ fsr:=get_fsr;
result:=[];
- { invalid operation: bit 27 }
- if (fsr and (1 shl 27))=0 then
+ { invalid operation }
+ if (fsr and fpu_enable_invalid)=0 then
include(result,exInvalidOp);
- { zero divide: bit 24 }
- if (fsr and (1 shl 24))=0 then
- include(result,exInvalidOp);
+ { zero divide }
+ if (fsr and fpu_enable_div_zero)=0 then
+ include(result,exZeroDivide);
- { overflow: bit 26 }
- if (fsr and (1 shl 26))=0 then
- include(result,exInvalidOp);
+ { overflow }
+ if (fsr and fpu_enable_overflow)=0 then
+ include(result,exOverflow);
- { underflow: bit 25 }
- if (fsr and (1 shl 25))=0 then
+ { underflow: }
+ if (fsr and fpu_enable_underflow)=0 then
include(result,exUnderflow);
- { Precision (inexact result): bit 23 }
- if (fsr and (1 shl 23))=0 then
+ { Precision (inexact result) }
+ if (fsr and fpu_enable_inexact)=0 then
include(result,exPrecision);
end;
@@ -100,40 +136,43 @@ function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
var
fsr : dword;
begin
-//!!! fsr:=get_fsr;
+ fsr:=get_fsr;
- { invalid operation: bit 27 }
+ { invalid operation }
if (exInvalidOp in mask) then
- fsr:=fsr and not(1 shl 27)
+ fsr:=fsr and not(fpu_enable_invalid)
else
- fsr:=fsr or (1 shl 27);
+ fsr:=fsr or (fpu_enable_invalid);
- { zero divide: bit 24 }
+ { zero divide }
if (exZeroDivide in mask) then
- fsr:=fsr and not(1 shl 24)
+ fsr:=fsr and not(fpu_enable_div_zero)
else
- fsr:=fsr or (1 shl 24);
+ fsr:=fsr or (fpu_enable_div_zero);
- { overflow: bit 26 }
+ { overflow }
if (exOverflow in mask) then
- fsr:=fsr and not(1 shl 26)
+ fsr:=fsr and not(fpu_enable_overflow)
else
- fsr:=fsr or (1 shl 26);
+ fsr:=fsr or (fpu_enable_overflow);
- { underflow: bit 25 }
+ { underflow }
if (exUnderflow in mask) then
- fsr:=fsr and not(1 shl 25)
+ fsr:=fsr and not(fpu_enable_underflow)
else
- fsr:=fsr or (1 shl 25);
+ fsr:=fsr or (fpu_enable_underflow);
- { Precision (inexact result): bit 23 }
+ { Precision (inexact result) }
if (exPrecision in mask) then
- fsr:=fsr and not(1 shl 23)
+ fsr:=fsr and not(fpu_enable_inexact)
else
- fsr:=fsr or (1 shl 23);
+ fsr:=fsr or (fpu_enable_inexact);
+
+ { Reset flags and cause }
+ fsr := fsr and not (fpu_flags_mask or fpu_cause_mask);
{ update control register contents }
-//!!! set_fsr(fsr);
+ set_fsr(fsr);
softfloat_exception_mask:=FPUExceptionMaskToSoftFloatMask(mask);
end;
@@ -141,6 +180,6 @@ function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
procedure ClearExceptions(RaisePending: Boolean =true);
begin
-//!!! set_fsr(get_fsr and $fffffc1f);
+ set_fsr(get_fsr and not (fpu_flags_mask or fpu_cause_mask));
end;