mathu.inc 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. member of the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. { exported by the system unit }
  12. function get_fsr : dword;external name 'FPC_GETFSR';
  13. procedure set_fsr(fsr : dword);external name 'FPC_SETFSR';
  14. const
  15. { FPU enable exception bits for FCSR register }
  16. fpu_enable_inexact = $80;
  17. fpu_enable_underflow = $100;
  18. fpu_enable_overflow = $200;
  19. fpu_enable_div_zero = $400;
  20. fpu_enable_invalid = $800;
  21. fpu_enable_mask = $F80;
  22. default_fpu_enable = fpu_enable_div_zero or fpu_enable_invalid;
  23. fpu_flags_mask = $7C;
  24. fpu_cause_mask = $3F000;
  25. { FPU rounding mask and values }
  26. fpu_rounding_mask = $3;
  27. fpu_rounding_nearest = 0;
  28. fpu_rounding_towards_zero = 1;
  29. fpu_rounding_plus_inf = 2;
  30. fpu_rounding_minus_inf = 3;
  31. function FPUExceptionMaskToSoftFloatMask(const Mask: TFPUExceptionMask): byte;
  32. begin
  33. result:=0;
  34. if exInvalidOp in Mask then
  35. result:=result or (1 shl ord(exInvalidOp));
  36. if exDenormalized in Mask then
  37. result:=result or (1 shl ord(exDenormalized));
  38. if exZeroDivide in Mask then
  39. result:=result or (1 shl ord(exZeroDivide));
  40. if exOverflow in Mask then
  41. result:=result or (1 shl ord(exOverflow));
  42. if exUnderflow in Mask then
  43. result:=result or (1 shl ord(exUnderflow));
  44. if exPrecision in Mask then
  45. result:=result or (1 shl ord(exPrecision));
  46. end;
  47. function GetRoundMode: TFPURoundingMode;
  48. begin
  49. result:=TFPURoundingMode(get_fsr and 3);
  50. end;
  51. function SetRoundMode(const RoundMode: TFPURoundingMode): TFPURoundingMode;
  52. var
  53. fpu_round : longint;
  54. begin
  55. case (RoundMode) of
  56. rmNearest :
  57. begin
  58. softfloat_rounding_mode := float_round_nearest_even;
  59. fpu_round:=fpu_rounding_nearest;
  60. end;
  61. rmTruncate :
  62. begin
  63. softfloat_rounding_mode := float_round_to_zero;
  64. fpu_round:=fpu_rounding_towards_zero;
  65. end;
  66. rmUp :
  67. begin
  68. softfloat_rounding_mode := float_round_up;
  69. fpu_round:=fpu_rounding_plus_inf;
  70. end;
  71. rmDown :
  72. begin
  73. softfloat_rounding_mode := float_round_down;
  74. fpu_round:=fpu_rounding_minus_inf;
  75. end;
  76. end;
  77. set_fsr((get_fsr and not fpu_rounding_mask) or fpu_round);
  78. //!!! result:=TFPURoundingMode(get_fsr shr 30);
  79. end;
  80. function GetPrecisionMode: TFPUPrecisionMode;
  81. begin
  82. result:=pmDouble;
  83. end;
  84. function SetPrecisionMode(const Precision: TFPUPrecisionMode): TFPUPrecisionMode;
  85. begin
  86. result:=pmDouble;
  87. end;
  88. function GetExceptionMask: TFPUExceptionMask;
  89. var
  90. fsr : dword;
  91. begin
  92. fsr:=get_fsr;
  93. result:=[];
  94. { invalid operation }
  95. if (fsr and fpu_enable_invalid)=0 then
  96. include(result,exInvalidOp);
  97. { zero divide }
  98. if (fsr and fpu_enable_div_zero)=0 then
  99. include(result,exZeroDivide);
  100. { overflow }
  101. if (fsr and fpu_enable_overflow)=0 then
  102. include(result,exOverflow);
  103. { underflow: }
  104. if (fsr and fpu_enable_underflow)=0 then
  105. include(result,exUnderflow);
  106. { Precision (inexact result) }
  107. if (fsr and fpu_enable_inexact)=0 then
  108. include(result,exPrecision);
  109. end;
  110. function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
  111. var
  112. fsr : dword;
  113. begin
  114. fsr:=get_fsr;
  115. { invalid operation }
  116. if (exInvalidOp in mask) then
  117. fsr:=fsr and not(fpu_enable_invalid)
  118. else
  119. fsr:=fsr or (fpu_enable_invalid);
  120. { zero divide }
  121. if (exZeroDivide in mask) then
  122. fsr:=fsr and not(fpu_enable_div_zero)
  123. else
  124. fsr:=fsr or (fpu_enable_div_zero);
  125. { overflow }
  126. if (exOverflow in mask) then
  127. fsr:=fsr and not(fpu_enable_overflow)
  128. else
  129. fsr:=fsr or (fpu_enable_overflow);
  130. { underflow }
  131. if (exUnderflow in mask) then
  132. fsr:=fsr and not(fpu_enable_underflow)
  133. else
  134. fsr:=fsr or (fpu_enable_underflow);
  135. { Precision (inexact result) }
  136. if (exPrecision in mask) then
  137. fsr:=fsr and not(fpu_enable_inexact)
  138. else
  139. fsr:=fsr or (fpu_enable_inexact);
  140. { Reset flags and cause }
  141. fsr := fsr and not (fpu_flags_mask or fpu_cause_mask);
  142. { update control register contents }
  143. set_fsr(fsr);
  144. softfloat_exception_mask:=FPUExceptionMaskToSoftFloatMask(mask);
  145. end;
  146. procedure ClearExceptions(RaisePending: Boolean =true);
  147. begin
  148. set_fsr(get_fsr and not (fpu_flags_mask or fpu_cause_mask));
  149. end;