mathu.inc 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2012 by Sven Barth
  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. {$if defined(FPU68881) or defined(FPUCOLDFIRE)}
  12. { 68881/2 FPCR Encodings
  13. Rounding Mode Rounding Precision
  14. (RND Field) Encoding (PREC Field)
  15. To Nearest (RN) 0 0 Extend (X)
  16. To Zero (RZ) 0 1 Single (S)
  17. To Minus Infinity (RM) 1 0 Double (D)
  18. To Plus Infinity (RP) 1 1 Undefined
  19. }
  20. { 68881/2 FPCR layout }
  21. { Exception Enable Byte: }
  22. { 15 - BSUN - Branch/Set on Unordered }
  23. { 14 - SNAN - Signal Not A Number }
  24. { 13 - OPERR - Operand Error }
  25. { 12 - OVFL - Overflow }
  26. { 11 - UNFL - Underflow }
  27. { 10 - DZ - Divide by Zero }
  28. { 09 - INEX2 - Inexact Operation }
  29. { 08 - INEX1 - Inexact Decimal Input }
  30. { Mode Control Byte: }
  31. { 07 - PREC - Rounding Precision }
  32. { 06 - PREC - Rounding Precision }
  33. { 05 - RND - Rounding Mode }
  34. { 04 - RND - Rounding Mode }
  35. { 03 - 0 - Reserved, Set to zero }
  36. { 02 - 0 - Reserved, Set to zero }
  37. { 01 - 0 - Reserved, Set to zero }
  38. { 00 - 0 - Reserved, Set to zero }
  39. {
  40. Please note that the rounding mode setting via FPCR in most emulators is broken.
  41. The list includes most versions and incarnations of UAE, MorphOS' Trance emulator,
  42. and others. The following code was verified to work on real hardware. (KB)
  43. }
  44. const
  45. FPU68K_ROUND_MASK_SHIFT = 4;
  46. FPU68K_ROUND_MASK = 3 shl FPU68K_ROUND_MASK_SHIFT;
  47. FPU68K_ROUND_NEAREST = 0 shl FPU68K_ROUND_MASK_SHIFT;
  48. FPU68K_ROUND_ZERO = 1 shl FPU68K_ROUND_MASK_SHIFT;
  49. FPU68K_ROUND_MINUSINF = 2 shl FPU68K_ROUND_MASK_SHIFT;
  50. FPU68K_ROUND_PLUSINF = 3 shl FPU68K_ROUND_MASK_SHIFT;
  51. const
  52. FPU68K_PREC_MASK_SHIFT = 6;
  53. FPU68K_PREC_MASK = 3 shl FPU68K_PREC_MASK_SHIFT;
  54. FPU68K_PREC_EXTENDED = 0 shl FPU68K_PREC_MASK_SHIFT;
  55. FPU68K_PREC_SINGLE = 1 shl FPU68K_PREC_MASK_SHIFT;
  56. FPU68K_PREC_DOUBLE = 2 shl FPU68K_PREC_MASK_SHIFT;
  57. const
  58. FPU68K_EXCEPT_MASK_SHIFT = 8;
  59. FPU68K_EXCEPT_MASK = 255 shl FPU68K_EXCEPT_MASK_SHIFT;
  60. FPU68K_EXCEPT_INEX1 = 1 shl (FPU68K_EXCEPT_MASK_SHIFT + 0);
  61. FPU68K_EXCEPT_INEX2 = 1 shl (FPU68K_EXCEPT_MASK_SHIFT + 1);
  62. FPU68K_EXCEPT_DZ = 1 shl (FPU68K_EXCEPT_MASK_SHIFT + 2);
  63. FPU68K_EXCEPT_UNFL = 1 shl (FPU68K_EXCEPT_MASK_SHIFT + 3);
  64. FPU68K_EXCEPT_OVFL = 1 shl (FPU68K_EXCEPT_MASK_SHIFT + 4);
  65. FPU68K_EXCEPT_OPERR = 1 shl (FPU68K_EXCEPT_MASK_SHIFT + 5);
  66. FPU68K_EXCEPT_SNAN = 1 shl (FPU68K_EXCEPT_MASK_SHIFT + 6);
  67. FPU68K_EXCEPT_BSUN = 1 shl (FPU68K_EXCEPT_MASK_SHIFt + 7);
  68. function GetExceptionMask: TFPUExceptionMask;
  69. begin
  70. Result := softfloat_exception_mask;
  71. end;
  72. function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
  73. const
  74. FPCToFPUExceptionFlags: array[TFPUException] of DWord =
  75. ( FPU68K_EXCEPT_OPERR, 0, FPU68K_EXCEPT_DZ, FPU68K_EXCEPT_OVFL, FPU68K_EXCEPT_UNFL, FPU68K_EXCEPT_INEX2 );
  76. FPUToFPCExceptionFlags: array[0..7] of TFPUExceptionMask =
  77. ( [], [exPrecision], [exZeroDivide], [exUnderflow], [exOverflow], [exInvalidOp], [], [] );
  78. var
  79. oldMode, Mode: DWord;
  80. e: TFPUException;
  81. i: longint;
  82. begin
  83. result:=[];
  84. oldMode:=(GetFPCR and FPU68K_EXCEPT_MASK) shr FPU68K_EXCEPT_MASK_SHIFT;
  85. for i:=low(FPUToFPCExceptionFlags) to high(FPUToFPCExceptionFlags) do
  86. if ((1 shl i) and oldMode) > 0 then
  87. result:=result+FPUToFPCExceptionFlags[i];
  88. mode:=0;
  89. for e in Mask do
  90. mode:=mode or FPCToFPUExceptionFlags[e];
  91. SetFPCR((GetFPCR and not FPU68K_EXCEPT_MASK) or (mode shl FPU68K_EXCEPT_MASK_SHIFT));
  92. softfloat_exception_mask:=mask;
  93. end;
  94. function GetRoundMode: TFPURoundingMode;
  95. const
  96. FPUToFPCRoundingMode: array[0..3] of TFPURoundingMode = ( rmNearest, rmTruncate, rmUp, rmDown );
  97. begin
  98. Result:=FPUToFPCRoundingMode[(GetFPCR and FPU68K_ROUND_MASK) shr FPU68K_ROUND_MASK_SHIFT];
  99. end;
  100. function SetRoundMode(const RoundMode: TFPURoundingMode): TFPURoundingMode;
  101. const
  102. FPCToFPURoundingMode: array[TFPURoundingMode] of DWord =
  103. ( FPU68K_ROUND_NEAREST, FPU68K_ROUND_MINUSINF, FPU68K_ROUND_PLUSINF, FPU68K_ROUND_ZERO );
  104. var
  105. FPCR: DWord;
  106. begin
  107. FPCR:=GetFPCR and not FPU68K_ROUND_MASK;
  108. SetFPCR(FPCR or FPCToFPURoundingMode[RoundMode]);
  109. softfloat_rounding_mode:=RoundMode;
  110. Result:=RoundMode;
  111. end;
  112. function GetPrecisionMode: TFPUPrecisionMode;
  113. begin
  114. result:=pmDouble;
  115. end;
  116. function SetPrecisionMode(const Precision: TFPUPrecisionMode): TFPUPrecisionMode;
  117. begin
  118. result:=pmDouble;
  119. end;
  120. procedure ClearExceptions(RaisePending: Boolean);
  121. begin
  122. SetFPCR(GetFPCR and not FPU68K_EXCEPT_MASK);
  123. SetFPSR(0);
  124. softfloat_exception_flags:=[];
  125. end;
  126. {$else}
  127. function GetExceptionMask: TFPUExceptionMask;
  128. begin
  129. Result := softfloat_exception_mask;
  130. end;
  131. function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
  132. begin
  133. result:=softfloat_exception_mask;
  134. softfloat_exception_mask:=mask;
  135. end;
  136. function GetRoundMode: TFPURoundingMode;
  137. begin
  138. Result:=softfloat_rounding_mode;
  139. end;
  140. function SetRoundMode(const RoundMode: TFPURoundingMode): TFPURoundingMode;
  141. begin
  142. Result:=softfloat_rounding_mode;
  143. softfloat_rounding_mode:=RoundMode;
  144. end;
  145. function GetPrecisionMode: TFPUPrecisionMode;
  146. begin
  147. result:=pmDouble;
  148. end;
  149. function SetPrecisionMode(const Precision: TFPUPrecisionMode): TFPUPrecisionMode;
  150. begin
  151. result:=pmDouble;
  152. end;
  153. procedure ClearExceptions(RaisePending: Boolean);
  154. begin
  155. softfloat_exception_flags:=[];
  156. end;
  157. {$endif}