ppcfpuex.inc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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. {$ifdef FPC_BIG_ENDIAN}
  42. lwz r3,temp.b
  43. {$else}
  44. lwz r3,temp.a
  45. {$endif}
  46. end;
  47. procedure fpc_set_ppc_fpsrc(cw: TNativeFPUControlWord);
  48. var
  49. cwtemp: qword;
  50. begin
  51. DefaultFPUControlWord:=cw;
  52. cwtemp:=cw;
  53. asm
  54. lfd f0, cwtemp
  55. mtfsf 255, f0
  56. end
  57. end;
  58. {$else aix}
  59. const
  60. FP_RND_RZ = 0;
  61. FP_RND_RN = 1;
  62. FP_RND_RP = 2;
  63. FP_RND_RM = 3;
  64. FP_TRAP_SYNC = 1; { precise trapping on }
  65. FP_TRAP_OFF = 0; { trapping off }
  66. FP_TRAP_QUERY = 2; { query trapping mode }
  67. FP_TRAP_IMP = 3; { non-recoverable imprecise trapping on }
  68. FP_TRAP_IMP_REC = 4; { recoverable imprecise trapping on }
  69. FP_TRAP_FASTMODE = 128; { select fastest available mode }
  70. FP_TRAP_ERROR = -1; { error condition }
  71. FP_TRAP_UNIMPL = -2; { requested mode not available }
  72. function fp_is_enabled(Mask: DWord): boolean;cdecl;external;
  73. procedure fp_enable(Mask: DWord);cdecl;external;
  74. function feclearexcept(Mask: DWord):DWord;cdecl;external;
  75. procedure fp_disable(Mask: DWord);cdecl;external;
  76. function fp_read_rnd: word;cdecl;external;
  77. function fp_swap_rnd(RoundMode: word): word;cdecl;external;
  78. function fp_trap(flag: longint): longint;cdecl; external;
  79. procedure fpc_setup_fpu;
  80. var
  81. cw: TNativeFPUControlWord;
  82. begin
  83. feclearexcept(InvalidOperationMask or OverflowMask or UnderflowMask or ZeroDivideMask or InexactMask);
  84. if fp_trap(FP_TRAP_SYNC)<0 then
  85. fp_trap(FP_TRAP_IMP_REC);
  86. cw:=GetNativeFPUControlWord;
  87. cw.rndmode:=FP_RND_RN;
  88. cw.exceptionmask:=InvalidOperationMask or ZeroDivideMask;
  89. SetNativeFPUControlWord(cw);
  90. end;
  91. function fpc_get_ppc_fpscr: TNativeFPUControlWord;
  92. begin
  93. result.rndmode:=fp_read_rnd;
  94. result.exceptionmask:=0;
  95. if fp_is_enabled(InvalidOperationMask) then
  96. result.exceptionmask:=result.exceptionmask or InvalidOperationMask;
  97. if fp_is_enabled(OverflowMask) then
  98. result.exceptionmask:=result.exceptionmask or OverflowMask;
  99. if fp_is_enabled(UnderflowMask) then
  100. result.exceptionmask:=result.exceptionmask or UnderflowMask;
  101. if fp_is_enabled(InvalidOperationMask) then
  102. result.exceptionmask:=result.exceptionmask or ZeroDivideMask;
  103. if fp_is_enabled(InexactMask) then
  104. result.exceptionmask:=result.exceptionmask or InexactMask;
  105. end;
  106. procedure fpc_set_ppc_fpsrc(cw: TNativeFPUControlWord);
  107. var
  108. enablemask, disablemask: dword;
  109. begin
  110. fp_swap_rnd(cw.rndmode);
  111. enablemask:=0;
  112. disablemask:=0;
  113. { this inverts the "mask" functionality, but that's because it's how the
  114. native PPC FPU control register works: the bits that are 1 enable the
  115. exceptions, 0 disable them. This makes sure that we can use
  116. SetNativeFPUControlWord in the same way regardless of what the underlying
  117. implementation is }
  118. if (cw.exceptionmask and InvalidOperationMask)<>0 then
  119. enablemask:=enablemask or InvalidOperationMask
  120. else
  121. disablemask:=disablemask or InvalidOperationMask;
  122. if (cw.exceptionmask and OverflowMask)<>0 then
  123. enablemask:=enablemask or OverflowMask
  124. else
  125. disablemask:=disablemask or OverflowMask;
  126. if (cw.exceptionmask and UnderflowMask)<>0 then
  127. enablemask:=enablemask or UnderflowMask
  128. else
  129. disablemask:=disablemask or UnderflowMask;
  130. if (cw.exceptionmask and ZeroDivideMask)<>0 then
  131. enablemask:=enablemask or ZeroDivideMask
  132. else
  133. disablemask:=disablemask or ZeroDivideMask;
  134. if (cw.exceptionmask and InexactMask)<>0 then
  135. enablemask:=enablemask or InexactMask
  136. else
  137. disablemask:=disablemask or InexactMask;
  138. fp_enable(enablemask);
  139. fp_disable(disablemask);
  140. DefaultFPUControlWord:=cw;
  141. end;
  142. {$endif}
  143. function GetNativeFPUControlWord: TNativeFPUControlWord; {$if defined(SYSTEMINLINE)}inline;{$endif}
  144. begin
  145. result:=fpc_get_ppc_fpscr;
  146. end;
  147. procedure SetNativeFPUControlWord(const cw: TNativeFPUControlWord); {$if defined(SYSTEMINLINE)}inline;{$endif}
  148. begin
  149. fpc_set_ppc_fpsrc(cw);
  150. end;
  151. {$define FPC_SYSTEM_HAS_SYSINITFPU}
  152. procedure SysInitFPU;{$ifdef SYSTEMINLINE}inline;{$endif}
  153. begin
  154. { powerpc might use softfloat code }
  155. softfloat_exception_flags:=[];
  156. softfloat_exception_mask:=[float_flag_underflow, float_flag_overflow, float_flag_inexact, float_flag_denormal];
  157. fpc_setup_fpu;
  158. end;
  159. {$endif NOT FPU_NONE}