mathu.inc 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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. {$asmmode gas}
  12. function getfpcr: dword; nostackframe; assembler;
  13. asm
  14. mrs x0,fpcr
  15. end;
  16. procedure setfpcr(val: dword); nostackframe; assembler;
  17. asm
  18. msr fpcr,x0
  19. end;
  20. function getfpsr: dword; nostackframe; assembler;
  21. asm
  22. mrs x0,fpsr
  23. end;
  24. procedure setfpsr(val: dword); nostackframe; assembler;
  25. asm
  26. msr fpsr, x0
  27. end;
  28. function GetRoundMode: TFPURoundingMode;
  29. const
  30. bits2rm: array[0..3] of TFPURoundingMode = (rmNearest,rmUp,rmDown,rmTruncate);
  31. begin
  32. result:=TFPURoundingMode(bits2rm[(getfpcr shr 22) and 3])
  33. end;
  34. function SetRoundMode(const RoundMode: TFPURoundingMode): TFPURoundingMode;
  35. const
  36. rm2bits: array[TFPURoundingMode] of byte = (0,2,1,3);
  37. begin
  38. softfloat_rounding_mode:=RoundMode;
  39. SetRoundMode:=RoundMode;
  40. setfpcr((getfpcr and $ff3fffff) or (rm2bits[RoundMode] shl 22));
  41. end;
  42. function GetPrecisionMode: TFPUPrecisionMode;
  43. begin
  44. result:=pmDouble;
  45. end;
  46. function SetPrecisionMode(const Precision: TFPUPrecisionMode): TFPUPrecisionMode;
  47. begin
  48. result:=pmDouble;
  49. end;
  50. const
  51. fpu_ioe = 1 shl 8;
  52. fpu_dze = 1 shl 9;
  53. fpu_ofe = 1 shl 10;
  54. fpu_ufe = 1 shl 11;
  55. fpu_ixe = 1 shl 12;
  56. fpu_ide = 1 shl 15;
  57. fpu_exception_mask = fpu_ioe or fpu_dze or fpu_ofe or fpu_ufe or fpu_ixe or fpu_ide;
  58. fpu_exception_mask_to_status_mask_shift = 8;
  59. function GetExceptionMask: TFPUExceptionMask;
  60. {
  61. var
  62. fpcr: dword;
  63. }
  64. begin
  65. { as I am not aware of any hardware exception supporting AArch64 implementation,
  66. and else the trapping enable flags are RAZ, return the softfloat exception mask (FK)
  67. fpcr:=getfpcr;
  68. result:=[];
  69. if ((fpcr and fpu_ioe)=0) then
  70. result := result+[exInvalidOp];
  71. if ((fpcr and fpu_ofe)=0) then
  72. result := result+[exOverflow];
  73. if ((fpcr and fpu_ufe)=0) then
  74. result := result+[exUnderflow];
  75. if ((fpcr and fpu_dze)=0) then
  76. result := result+[exZeroDivide];
  77. if ((fpcr and fpu_ixe)=0) then
  78. result := result+[exPrecision];
  79. if ((fpcr and fpu_ide)=0) then
  80. result := result+[exDenormalized];
  81. }
  82. result:=softfloat_exception_mask;
  83. end;
  84. function SetExceptionMask(const Mask: TFPUExceptionMask): TFPUExceptionMask;
  85. {
  86. var
  87. newfpcr: dword;
  88. }
  89. begin
  90. { as I am not aware of any hardware exception supporting AArch64 implementation,
  91. and else the trapping enable flags are RAZ, work solely with softfloat_exception_mask (FK)
  92. }
  93. softfloat_exception_mask:=mask;
  94. {
  95. newfpcr:=fpu_exception_mask;
  96. if exInvalidOp in Mask then
  97. newfpcr:=newfpcr and not(fpu_ioe);
  98. if exOverflow in Mask then
  99. newfpcr:=newfpcr and not(fpu_ofe);
  100. if exUnderflow in Mask then
  101. newfpcr:=newfpcr and not(fpu_ufe);
  102. if exZeroDivide in Mask then
  103. newfpcr:=newfpcr and not(fpu_dze);
  104. if exPrecision in Mask then
  105. newfpcr:=newfpcr and not(fpu_ixe);
  106. if exDenormalized in Mask then
  107. newfpcr:=newfpcr and not(fpu_ide);
  108. }
  109. { clear "exception happened" flags }
  110. ClearExceptions(false);
  111. { set new exception mask }
  112. // setfpcr((getfpcr and not(fpu_exception_mask)) or newfpcr);
  113. { unsupported mask bits will remain 0 -> read exception mask again }
  114. // result:=GetExceptionMask;
  115. // softfloat_exception_mask:=result;
  116. result:=softfloat_exception_mask;
  117. end;
  118. procedure ClearExceptions(RaisePending: Boolean);
  119. var
  120. fpsr: dword;
  121. f: TFPUException;
  122. begin
  123. fpsr:=getfpsr;
  124. if raisepending then
  125. begin
  126. if (fpsr and (fpu_dze shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
  127. float_raise(exZeroDivide);
  128. if (fpsr and (fpu_ofe shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
  129. float_raise(exOverflow);
  130. if (fpsr and (fpu_ufe shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
  131. float_raise(exUnderflow);
  132. if (fpsr and (fpu_ioe shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
  133. float_raise(exInvalidOp);
  134. if (fpsr and (fpu_ixe shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
  135. float_raise(exPrecision);
  136. if (fpsr and (fpu_ide shr fpu_exception_mask_to_status_mask_shift)) <> 0 then
  137. float_raise(exDenormalized);
  138. { now the soft float exceptions }
  139. for f in softfloat_exception_flags do
  140. float_raise(f);
  141. end;
  142. softfloat_exception_flags:=[];
  143. setfpsr(fpsr and not(fpu_exception_mask shr fpu_exception_mask_to_status_mask_shift));
  144. end;