mathu.inc 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2005 by Thomas Schatzl
  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. const
  12. RoundModeMask = %00000011;
  13. NonIEEEModeMask = %00000100;
  14. InvalidOperationMask = %10000000;
  15. OverflowMask = %01000000;
  16. UnderflowMask = %00100000;
  17. ZeroDivideMask = %00010000;
  18. InexactMask = %00001000;
  19. AllExceptionsMask = %11111000;
  20. ExceptionsPendingMask = %11111111111111100000011100000000;
  21. ExceptionMask = InvalidOperationMask or OverflowMask or UnderflowMask or ZeroDivideMask or InexactMask;
  22. AllConfigBits = ExceptionMask or NonIEEEModeMask or RoundModeMask;
  23. function getFPSCR : DWord; assembler; nostackframe;
  24. asm
  25. mffs f0
  26. stfd f0, -12(r1)
  27. lwz r3, -8(r1)
  28. end;
  29. procedure setFPSCR(newFPSCR : DWord); assembler; nostackframe;
  30. asm
  31. stw r3, -8(r1)
  32. lfd f0, -12(r1)
  33. mtfsf 255, f0
  34. end;
  35. {$ifdef aix}
  36. const
  37. FP_RND_RZ = 0;
  38. FP_RND_RN = 1;
  39. FP_RND_RP = 2;
  40. FP_RND_RM = 3;
  41. function fp_is_enabled(Mask: DWord): boolean;cdecl;external;
  42. procedure fp_enable(Mask: DWord);cdecl;external;
  43. function feclearexcept(Mask: DWord):DWord;cdecl;external;
  44. procedure fp_disable(Mask: DWord);cdecl;external;
  45. function fp_read_rnd: word;cdecl;external;
  46. function fp_swap_rnd(RoundMode: word): word;cdecl;external;
  47. {$else aix}
  48. const
  49. FP_RND_RZ = 1;
  50. FP_RND_RN = 0;
  51. FP_RND_RP = 2;
  52. FP_RND_RM = 3;
  53. {$endif aix}
  54. function GetRoundMode: TFPURoundingMode;
  55. begin
  56. {$ifndef aix}
  57. case (getFPSCR and RoundModeMask) of
  58. {$else not aix}
  59. case fp_read_rnd of
  60. {$endif not aix}
  61. FP_RND_RN : result := rmNearest;
  62. FP_RND_RZ : result := rmTruncate;
  63. FP_RND_RP : result := rmUp;
  64. FP_RND_RM : result := rmDown;
  65. end;
  66. end;
  67. function SetRoundMode(const RoundMode: TFPURoundingMode): TFPURoundingMode;
  68. var
  69. mode : DWord;
  70. begin
  71. case (RoundMode) of
  72. rmNearest :
  73. begin
  74. mode := FP_RND_RN;
  75. softfloat_rounding_mode := float_round_nearest_even;
  76. end;
  77. rmTruncate :
  78. begin
  79. mode := FP_RND_RZ;
  80. softfloat_rounding_mode := float_round_to_zero;
  81. end;
  82. rmUp :
  83. begin
  84. mode := FP_RND_RP;
  85. softfloat_rounding_mode := float_round_up;
  86. end;
  87. rmDown :
  88. begin
  89. mode := FP_RND_RM;
  90. softfloat_rounding_mode := float_round_down;
  91. end;
  92. end;
  93. {$ifndef aix}
  94. setFPSCR((getFPSCR and (not RoundModeMask)) or mode);
  95. {$else not aix}
  96. fp_swap_rnd(mode);
  97. {$endif not aix}
  98. result := RoundMode;
  99. end;
  100. function GetPrecisionMode: TFPUPrecisionMode;
  101. begin
  102. result := pmDouble;
  103. end;
  104. function SetPrecisionMode(const Precision: TFPUPrecisionMode): TFPUPrecisionMode;
  105. begin
  106. { nothing to do, not supported }
  107. result := pmDouble;
  108. end;
  109. function GetExceptionMask: TFPUExceptionMask;
  110. begin
  111. result := [];
  112. {$ifndef aix}
  113. if ((getFPSCR and InvalidOperationMask) = 0) then
  114. result := result + [exInvalidOp];
  115. if ((getFPSCR and OverflowMask) = 0) then
  116. result := result + [exOverflow];
  117. if ((getFPSCR and UnderflowMask) = 0) then
  118. result := result + [exUnderflow];
  119. if ((getFPSCR and ZeroDivideMask) = 0) then
  120. result := result + [exZeroDivide];
  121. if ((getFPSCR and InexactMask) = 0) then
  122. result := result + [exPrecision];
  123. {$else not aix}
  124. if not fp_is_enabled(InvalidOperationMask) then
  125. result := result + [exInvalidOp];
  126. if not fp_is_enabled(OverflowMask) then
  127. result := result + [exOverflow];
  128. if not fp_is_enabled(UnderflowMask) then
  129. result := result + [exUnderflow];
  130. if not fp_is_enabled(ZeroDivideMask) then
  131. result := result + [exZeroDivide];
  132. if not fp_is_enabled(InexactMask) then
  133. result := result + [exPrecision];
  134. {$endif not aix}
  135. end;
  136. function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
  137. var
  138. mode : DWord;
  139. begin
  140. mode := 0;
  141. softfloat_exception_mask := 0;
  142. if (exInvalidOp in Mask) then
  143. begin
  144. mode := mode or InvalidOperationMask;
  145. softfloat_exception_mask := softfloat_exception_mask or float_flag_invalid;
  146. end;
  147. if (exOverflow in Mask) then
  148. begin
  149. mode := mode or OverflowMask;
  150. softfloat_exception_mask := softfloat_exception_mask or float_flag_overflow;
  151. end;
  152. if (exUnderflow in Mask) then
  153. begin
  154. mode := mode or UnderflowMask;
  155. softfloat_exception_mask := softfloat_exception_mask or float_flag_underflow;
  156. end;
  157. if (exZeroDivide in Mask) then
  158. begin
  159. mode := mode or ZeroDivideMask;
  160. softfloat_exception_mask := softfloat_exception_mask or float_flag_divbyzero;
  161. end;
  162. if (exPrecision in Mask) then
  163. begin
  164. mode := mode or InexactMask;
  165. softfloat_exception_mask := softfloat_exception_mask or float_flag_inexact;
  166. end;
  167. setFPSCR((getFPSCR or ExceptionMask) and not mode and not ExceptionsPendingMask);
  168. softfloat_exception_flags := 0;;
  169. { also clear out pending exceptions on AIX }
  170. {$ifdef aix}
  171. { clear pending exceptions }
  172. feclearexcept(AllExceptionsMask);
  173. { enable the exceptions that are not disabled }
  174. fp_enable(mode xor AllExceptionsMask);
  175. { and disable the rest }
  176. fp_disable(mode);
  177. {$endif}
  178. result := Mask - [exDenormalized];
  179. end;
  180. procedure ClearExceptions(RaisePending: Boolean = true);
  181. begin
  182. {$ifdef aix}
  183. { clear pending exceptions }
  184. feclearexcept(AllExceptionsMask);
  185. {$endif}
  186. softfloat_exception_flags := 0;
  187. { RaisePending has no effect on PPC, always raises them at the correct location }
  188. setFPSCR(getFPSCR and (not ExceptionsPendingMask));
  189. end;