mathu.inc 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2014 by Jonas Maebe
  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. function getcause: dword; nostackframe; assembler;
  12. asm
  13. movfcsr2gr $a0, $r2
  14. srli.w $a0, $a0, 24
  15. end;
  16. procedure clearcause; nostackframe; assembler;
  17. asm
  18. movgr2fcsr $r2, $zero
  19. end;
  20. function GetRoundMode: TFPURoundingMode;
  21. var
  22. cw: TNativeFPUControlWord;
  23. const
  24. bits2rm: array[0..3] of TFPURoundingMode = (rmNearest,rmTruncate,rmUp,rmDown);
  25. begin
  26. cw:=GetNativeFPUControlWord;
  27. result:=TFPURoundingMode(bits2rm[cw.rndmode])
  28. end;
  29. function SetRoundMode(const RoundMode: TFPURoundingMode): TFPURoundingMode;
  30. var
  31. cw: TNativeFPUControlWord;
  32. const
  33. rm2bits : array[TFPURoundingMode] of byte = (0,3,2,1);
  34. begin
  35. softfloat_rounding_mode:=RoundMode;
  36. SetRoundMode:=GetRoundMode;
  37. cw:=GetNativeFPUControlWord;
  38. cw.rndmode:=rm2bits[RoundMode];
  39. SetNativeFPUControlWord(cw);
  40. end;
  41. function GetPrecisionMode: TFPUPrecisionMode;
  42. begin
  43. result:=pmDouble;
  44. end;
  45. function SetPrecisionMode(const Precision: TFPUPrecisionMode): TFPUPrecisionMode;
  46. begin
  47. result:=pmDouble;
  48. end;
  49. const
  50. fpu_i = 1 shl 0;
  51. fpu_u = 1 shl 1;
  52. fpu_o = 1 shl 2;
  53. fpu_z = 1 shl 3;
  54. fpu_v = 1 shl 4;
  55. function GetExceptionMask: TFPUExceptionMask;
  56. begin
  57. Result:=softfloat_exception_mask;
  58. end;
  59. function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
  60. var
  61. newenables: qword;
  62. cw: TNativeFPUControlWord;
  63. begin
  64. { clear "exception happened" flags }
  65. ClearExceptions(false);
  66. result:=softfloat_exception_mask;
  67. softfloat_exception_mask:=Mask;
  68. newenables:=$1f;
  69. if exPrecision in Mask then
  70. newenables:=newenables and not(fpu_i);
  71. if exUnderflow in Mask then
  72. newenables:=newenables and not(fpu_u);
  73. if exOverflow in Mask then
  74. newenables:=newenables and not(fpu_o);
  75. if exZeroDivide in Mask then
  76. newenables:=newenables and not(fpu_z);
  77. if exInvalidOp in Mask then
  78. newenables:=newenables and not(fpu_v);
  79. cw:=GetNativeFPUControlWord;
  80. cw.cw:=newenables;
  81. SetNativeFPUControlWord(cw);
  82. end;
  83. procedure RaisePendingExceptions;
  84. var
  85. cause : dword;
  86. f: TFPUException;
  87. begin
  88. cause:=getcause;
  89. if (cause and fpu_i) <> 0 then
  90. float_raise(exPrecision);
  91. if (cause and fpu_u) <> 0 then
  92. float_raise(exUnderflow);
  93. if (cause and fpu_o) <> 0 then
  94. float_raise(exOverflow);
  95. if (cause and fpu_z) <> 0 then
  96. float_raise(exZeroDivide);
  97. if (cause and fpu_v) <> 0 then
  98. float_raise(exInvalidOp);
  99. { now the soft float exceptions }
  100. for f in softfloat_exception_flags do
  101. float_raise(f);
  102. end;
  103. procedure ClearExceptions(RaisePending: Boolean);
  104. begin
  105. if raisepending then
  106. RaisePendingExceptions;
  107. softfloat_exception_flags:=[];
  108. clearcause;
  109. end;