ppcfpuex.inc 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. {$ifndef FPUNONE}
  2. const
  3. InvalidOperationMask = %10000000;
  4. OverflowMask = %01000000;
  5. UnderflowMask = %00100000;
  6. ZeroDivideMask = %00010000;
  7. InexactMask = %00001000;
  8. {$ifndef aix}
  9. const
  10. FP_RND_RZ = 1;
  11. FP_RND_RN = 0;
  12. FP_RND_RP = 2;
  13. FP_RND_RM = 3;
  14. FP_RND_SHIFT = 28;
  15. FP_RND_MASK = 3;
  16. procedure fpc_setup_fpu;
  17. var
  18. cw: TNativeFPUControlWord;
  19. begin
  20. asm
  21. { clear all "exception happened" flags we care about}
  22. mtfsfi 0,0
  23. mtfsfi 1,0
  24. mtfsfi 2,0
  25. mtfsfi 3,0
  26. mtfsb0 21
  27. mtfsb0 22
  28. mtfsb0 23
  29. end;
  30. cw:=GetNativeFPUControlWord;
  31. cw:=(cw and not(OverflowMask or UnderflowMask or InexactMask or (FP_RND_MASK shl FP_RND_SHIFT))) or InvalidOperationMask or ZeroDivideMask or (FP_RND_RN shl FP_RND_SHIFT);
  32. SetNativeFPUControlWord(cw);
  33. end;
  34. function fpc_get_ppc_fpscr: TNativeFPUControlWord;
  35. assembler;
  36. var
  37. temp: record a,b:longint; end;
  38. asm
  39. mffs f0
  40. stfd f0,temp
  41. lwz r3,temp.b
  42. end;
  43. procedure fpc_set_ppc_fpsrc(cw: TNativeFPUControlWord);
  44. var
  45. cwtemp: qword;
  46. begin
  47. DefaultFPUControlWord:=cw;
  48. cwtemp:=cw;
  49. asm
  50. lfd f0, cwtemp
  51. mtfsf 255, f0
  52. end
  53. end;
  54. {$else aix}
  55. const
  56. FP_RND_RZ = 0;
  57. FP_RND_RN = 1;
  58. FP_RND_RP = 2;
  59. FP_RND_RM = 3;
  60. FP_TRAP_SYNC = 1; { precise trapping on }
  61. FP_TRAP_OFF = 0; { trapping off }
  62. FP_TRAP_QUERY = 2; { query trapping mode }
  63. FP_TRAP_IMP = 3; { non-recoverable imprecise trapping on }
  64. FP_TRAP_IMP_REC = 4; { recoverable imprecise trapping on }
  65. FP_TRAP_FASTMODE = 128; { select fastest available mode }
  66. FP_TRAP_ERROR = -1; { error condition }
  67. FP_TRAP_UNIMPL = -2; { requested mode not available }
  68. function fp_is_enabled(Mask: DWord): boolean;cdecl;external;
  69. procedure fp_enable(Mask: DWord);cdecl;external;
  70. function feclearexcept(Mask: DWord):DWord;cdecl;external;
  71. procedure fp_disable(Mask: DWord);cdecl;external;
  72. function fp_read_rnd: word;cdecl;external;
  73. function fp_swap_rnd(RoundMode: word): word;cdecl;external;
  74. function fp_trap(flag: longint): longint;cdecl; external;
  75. procedure fpc_setup_fpu;
  76. var
  77. cw: TNativeFPUControlWord;
  78. begin
  79. feclearexcept(InvalidOperationMask or OverflowMask or UnderflowMask or ZeroDivideMask or InexactMask);
  80. if fp_trap(FP_TRAP_SYNC)<0 then
  81. fp_trap(FP_TRAP_IMP_REC);
  82. cw:=GetNativeFPUControlWord;
  83. cw.rndmode:=FP_RND_RN;
  84. cw.exceptionmask:=InvalidOperationMask or ZeroDivideMask;
  85. SetNativeFPUControlWord(cw);
  86. end;
  87. function fpc_get_ppc_fpscr: TNativeFPUControlWord;
  88. begin
  89. result.rndmode:=fp_read_rnd;
  90. result.exceptionmask:=0;
  91. if not fp_is_enabled(InvalidOperationMask) then
  92. result.exceptionmask:=result.exceptionmask or InvalidOperationMask;
  93. if not fp_is_enabled(OverflowMask) then
  94. result.exceptionmask:=result.exceptionmask or OverflowMask;
  95. if not fp_is_enabled(UnderflowMask) then
  96. result.exceptionmask:=result.exceptionmask or UnderflowMask;
  97. if not fp_is_enabled(InvalidOperationMask) then
  98. result.exceptionmask:=result.exceptionmask or ZeroDivideMask;
  99. if not fp_is_enabled(InexactMask) then
  100. result.exceptionmask:=result.exceptionmask or InexactMask;
  101. end;
  102. procedure fpc_set_ppc_fpsrc(cw: TNativeFPUControlWord);
  103. var
  104. enablemask, disablemask: dword;
  105. begin
  106. fp_swap_rnd(cw.rndmode);
  107. enablemask:=0;
  108. disablemask:=0;
  109. if (cw.exceptionmask and InvalidOperationMask)<>0 then
  110. disablemask:=disablemask or InvalidOperationMask
  111. else
  112. enablemask:=enablemask or InvalidOperationMask;
  113. if (cw.exceptionmask and OverflowMask)<>0 then
  114. disablemask:=disablemask or OverflowMask
  115. else
  116. enablemask:=enablemask or OverflowMask;
  117. if (cw.exceptionmask and UnderflowMask)<>0 then
  118. disablemask:=disablemask or UnderflowMask
  119. else
  120. enablemask:=enablemask or UnderflowMask;
  121. if (cw.exceptionmask and ZeroDivideMask)<>0 then
  122. disablemask:=disablemask or ZeroDivideMask
  123. else
  124. enablemask:=enablemask or ZeroDivideMask;
  125. if (cw.exceptionmask and InexactMask)<>0 then
  126. disablemask:=disablemask or InexactMask
  127. else
  128. enablemask:=enablemask or InexactMask;
  129. fp_enable(enablemask);
  130. fp_disable(disablemask);
  131. DefaultFPUControlWord:=cw;
  132. end;
  133. {$endif}
  134. function GetNativeFPUControlWord: TNativeFPUControlWord; {$if defined(SYSTEMINLINE)}inline;{$endif}
  135. begin
  136. result:=fpc_get_ppc_fpscr;
  137. end;
  138. procedure SetNativeFPUControlWord(const cw: TNativeFPUControlWord); {$if defined(SYSTEMINLINE)}inline;{$endif}
  139. begin
  140. fpc_set_ppc_fpsrc(cw);
  141. end;
  142. {$define FPC_SYSTEM_HAS_SYSINITFPU}
  143. procedure SysInitFPU;{$ifdef SYSTEMINLINE}inline;{$endif}
  144. begin
  145. { powerpc might use softfloat code }
  146. softfloat_exception_flags:=[];
  147. softfloat_exception_mask:=[float_flag_underflow, float_flag_overflow, float_flag_inexact, float_flag_denormal];
  148. fpc_setup_fpu;
  149. end;
  150. {$endif NOT FPU_NONE}