fpu-aix.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. /* AIX FPU-related code.
  2. Copyright (C) 2005-2015 Free Software Foundation, Inc.
  3. Contributed by Francois-Xavier Coudert <coudert@clipper.ens.fr>
  4. This file is part of the GNU Fortran runtime library (libgfortran).
  5. Libgfortran is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public
  7. License as published by the Free Software Foundation; either
  8. version 3 of the License, or (at your option) any later version.
  9. Libgfortran is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. Under Section 7 of GPL version 3, you are granted additional
  14. permissions described in the GCC Runtime Library Exception, version
  15. 3.1, as published by the Free Software Foundation.
  16. You should have received a copy of the GNU General Public License and
  17. a copy of the GCC Runtime Library Exception along with this program;
  18. see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. <http://www.gnu.org/licenses/>. */
  20. /* FPU-related code for AIX. */
  21. #ifdef HAVE_FPTRAP_H
  22. #include <fptrap.h>
  23. #endif
  24. #ifdef HAVE_FPXCP_H
  25. #include <fpxcp.h>
  26. #endif
  27. #ifdef HAVE_FENV_H
  28. #include <fenv.h>
  29. #endif
  30. /* Check we can actually store the FPU state in the allocated size. */
  31. _Static_assert (sizeof(fenv_t) <= (size_t) GFC_FPE_STATE_BUFFER_SIZE,
  32. "GFC_FPE_STATE_BUFFER_SIZE is too small");
  33. void
  34. set_fpu_trap_exceptions (int trap, int notrap)
  35. {
  36. fptrap_t mode_set = 0, mode_clr = 0;
  37. #ifdef TRP_INVALID
  38. if (trap & GFC_FPE_INVALID)
  39. mode_set |= TRP_INVALID;
  40. if (notrap & GFC_FPE_INVALID)
  41. mode_clr |= TRP_INVALID;
  42. #endif
  43. #ifdef TRP_DIV_BY_ZERO
  44. if (trap & GFC_FPE_ZERO)
  45. mode_set |= TRP_DIV_BY_ZERO;
  46. if (notrap & GFC_FPE_ZERO)
  47. mode_clr |= TRP_DIV_BY_ZERO;
  48. #endif
  49. #ifdef TRP_OVERFLOW
  50. if (trap & GFC_FPE_OVERFLOW)
  51. mode_set |= TRP_OVERFLOW;
  52. if (notrap & GFC_FPE_OVERFLOW)
  53. mode_clr |= TRP_OVERFLOW;
  54. #endif
  55. #ifdef TRP_UNDERFLOW
  56. if (trap & GFC_FPE_UNDERFLOW)
  57. mode_set |= TRP_UNDERFLOW;
  58. if (notrap & GFC_FPE_UNDERFLOW)
  59. mode_clr |= TRP_UNDERFLOW;
  60. #endif
  61. #ifdef TRP_INEXACT
  62. if (trap & GFC_FPE_INEXACT)
  63. mode_set |= TRP_INEXACT;
  64. if (notrap & GFC_FPE_INEXACT)
  65. mode_clr |= TRP_INEXACT;
  66. #endif
  67. fp_trap (FP_TRAP_SYNC);
  68. fp_enable (mode_set);
  69. fp_disable (mode_clr);
  70. }
  71. int
  72. get_fpu_trap_exceptions (void)
  73. {
  74. int res = 0;
  75. #ifdef TRP_INVALID
  76. if (fp_is_enabled (TRP_INVALID))
  77. res |= GFC_FPE_INVALID;
  78. #endif
  79. #ifdef TRP_DIV_BY_ZERO
  80. if (fp_is_enabled (TRP_DIV_BY_ZERO))
  81. res |= GFC_FPE_ZERO;
  82. #endif
  83. #ifdef TRP_OVERFLOW
  84. if (fp_is_enabled (TRP_OVERFLOW))
  85. res |= GFC_FPE_OVERFLOW;
  86. #endif
  87. #ifdef TRP_UNDERFLOW
  88. if (fp_is_enabled (TRP_UNDERFLOW))
  89. res |= GFC_FPE_UNDERFLOW;
  90. #endif
  91. #ifdef TRP_INEXACT
  92. if (fp_is_enabled (TRP_INEXACT))
  93. res |= GFC_FPE_INEXACT;
  94. #endif
  95. return res;
  96. }
  97. int
  98. support_fpu_trap (int flag)
  99. {
  100. return support_fpu_flag (flag);
  101. }
  102. void
  103. set_fpu (void)
  104. {
  105. #ifndef TRP_INVALID
  106. if (options.fpe & GFC_FPE_INVALID)
  107. estr_write ("Fortran runtime warning: IEEE 'invalid operation' "
  108. "exception not supported.\n");
  109. #endif
  110. if (options.fpe & GFC_FPE_DENORMAL)
  111. estr_write ("Fortran runtime warning: Floating point 'denormal operand' "
  112. "exception not supported.\n");
  113. #ifndef TRP_DIV_BY_ZERO
  114. if (options.fpe & GFC_FPE_ZERO)
  115. estr_write ("Fortran runtime warning: IEEE 'division by zero' "
  116. "exception not supported.\n");
  117. #endif
  118. #ifndef TRP_OVERFLOW
  119. if (options.fpe & GFC_FPE_OVERFLOW)
  120. estr_write ("Fortran runtime warning: IEEE 'overflow' "
  121. "exception not supported.\n");
  122. #endif
  123. #ifndef TRP_UNDERFLOW
  124. if (options.fpe & GFC_FPE_UNDERFLOW)
  125. estr_write ("Fortran runtime warning: IEEE 'underflow' "
  126. "exception not supported.\n");
  127. #endif
  128. #ifndef TRP_INEXACT
  129. if (options.fpe & GFC_FPE_INEXACT)
  130. estr_write ("Fortran runtime warning: IEEE 'inexact' "
  131. "exception not supported.\n");
  132. #endif
  133. set_fpu_trap_exceptions (options.fpe, 0);
  134. }
  135. int
  136. get_fpu_except_flags (void)
  137. {
  138. int result, set_excepts;
  139. result = 0;
  140. #ifdef HAVE_FPXCP_H
  141. if (!fp_any_xcp ())
  142. return 0;
  143. if (fp_invalid_op ())
  144. result |= GFC_FPE_INVALID;
  145. if (fp_divbyzero ())
  146. result |= GFC_FPE_ZERO;
  147. if (fp_overflow ())
  148. result |= GFC_FPE_OVERFLOW;
  149. if (fp_underflow ())
  150. result |= GFC_FPE_UNDERFLOW;
  151. if (fp_inexact ())
  152. result |= GFC_FPE_INEXACT;
  153. #endif
  154. return result;
  155. }
  156. void
  157. set_fpu_except_flags (int set, int clear)
  158. {
  159. int exc_set = 0, exc_clr = 0;
  160. #ifdef FP_INVALID
  161. if (set & GFC_FPE_INVALID)
  162. exc_set |= FP_INVALID;
  163. else if (clear & GFC_FPE_INVALID)
  164. exc_clr |= FP_INVALID;
  165. #endif
  166. #ifdef FP_DIV_BY_ZERO
  167. if (set & GFC_FPE_ZERO)
  168. exc_set |= FP_DIV_BY_ZERO;
  169. else if (clear & GFC_FPE_ZERO)
  170. exc_clr |= FP_DIV_BY_ZERO;
  171. #endif
  172. #ifdef FP_OVERFLOW
  173. if (set & GFC_FPE_OVERFLOW)
  174. exc_set |= FP_OVERFLOW;
  175. else if (clear & GFC_FPE_OVERFLOW)
  176. exc_clr |= FP_OVERFLOW;
  177. #endif
  178. #ifdef FP_UNDERFLOW
  179. if (set & GFC_FPE_UNDERFLOW)
  180. exc_set |= FP_UNDERFLOW;
  181. else if (clear & GFC_FPE_UNDERFLOW)
  182. exc_clr |= FP_UNDERFLOW;
  183. #endif
  184. /* AIX does not have FP_DENORMAL. */
  185. #ifdef FP_INEXACT
  186. if (set & GFC_FPE_INEXACT)
  187. exc_set |= FP_INEXACT;
  188. else if (clear & GFC_FPE_INEXACT)
  189. exc_clr |= FP_INEXACT;
  190. #endif
  191. fp_clr_flag (exc_clr);
  192. fp_set_flag (exc_set);
  193. }
  194. int
  195. support_fpu_flag (int flag)
  196. {
  197. if (flag & GFC_FPE_INVALID)
  198. {
  199. #ifndef FP_INVALID
  200. return 0;
  201. #endif
  202. }
  203. else if (flag & GFC_FPE_ZERO)
  204. {
  205. #ifndef FP_DIV_BY_ZERO
  206. return 0;
  207. #endif
  208. }
  209. else if (flag & GFC_FPE_OVERFLOW)
  210. {
  211. #ifndef FP_OVERFLOW
  212. return 0;
  213. #endif
  214. }
  215. else if (flag & GFC_FPE_UNDERFLOW)
  216. {
  217. #ifndef FP_UNDERFLOW
  218. return 0;
  219. #endif
  220. }
  221. else if (flag & GFC_FPE_DENORMAL)
  222. {
  223. /* AIX does not support denormal flag. */
  224. return 0;
  225. }
  226. else if (flag & GFC_FPE_INEXACT)
  227. {
  228. #ifndef FP_INEXACT
  229. return 0;
  230. #endif
  231. }
  232. return 1;
  233. }
  234. int
  235. get_fpu_rounding_mode (void)
  236. {
  237. int rnd_mode;
  238. rnd_mode = fegetround ();
  239. switch (rnd_mode)
  240. {
  241. #ifdef FE_TONEAREST
  242. case FE_TONEAREST:
  243. return GFC_FPE_TONEAREST;
  244. #endif
  245. #ifdef FE_UPWARD
  246. case FE_UPWARD:
  247. return GFC_FPE_UPWARD;
  248. #endif
  249. #ifdef FE_DOWNWARD
  250. case FE_DOWNWARD:
  251. return GFC_FPE_DOWNWARD;
  252. #endif
  253. #ifdef FE_TOWARDZERO
  254. case FE_TOWARDZERO:
  255. return GFC_FPE_TOWARDZERO;
  256. #endif
  257. default:
  258. return 0; /* Should be unreachable. */
  259. }
  260. }
  261. void
  262. set_fpu_rounding_mode (int mode)
  263. {
  264. int rnd_mode;
  265. switch (mode)
  266. {
  267. #ifdef FE_TONEAREST
  268. case GFC_FPE_TONEAREST:
  269. rnd_mode = FE_TONEAREST;
  270. break;
  271. #endif
  272. #ifdef FE_UPWARD
  273. case GFC_FPE_UPWARD:
  274. rnd_mode = FE_UPWARD;
  275. break;
  276. #endif
  277. #ifdef FE_DOWNWARD
  278. case GFC_FPE_DOWNWARD:
  279. rnd_mode = FE_DOWNWARD;
  280. break;
  281. #endif
  282. #ifdef FE_TOWARDZERO
  283. case GFC_FPE_TOWARDZERO:
  284. rnd_mode = FE_TOWARDZERO;
  285. break;
  286. #endif
  287. default:
  288. return; /* Should be unreachable. */
  289. }
  290. fesetround (rnd_mode);
  291. }
  292. int
  293. support_fpu_rounding_mode (int mode)
  294. {
  295. switch (mode)
  296. {
  297. case GFC_FPE_TONEAREST:
  298. #ifdef FE_TONEAREST
  299. return 1;
  300. #else
  301. return 0;
  302. #endif
  303. case GFC_FPE_UPWARD:
  304. #ifdef FE_UPWARD
  305. return 1;
  306. #else
  307. return 0;
  308. #endif
  309. case GFC_FPE_DOWNWARD:
  310. #ifdef FE_DOWNWARD
  311. return 1;
  312. #else
  313. return 0;
  314. #endif
  315. case GFC_FPE_TOWARDZERO:
  316. #ifdef FE_TOWARDZERO
  317. return 1;
  318. #else
  319. return 0;
  320. #endif
  321. default:
  322. return 0; /* Should be unreachable. */
  323. }
  324. }
  325. void
  326. get_fpu_state (void *state)
  327. {
  328. fegetenv (state);
  329. }
  330. void
  331. set_fpu_state (void *state)
  332. {
  333. fesetenv (state);
  334. }
  335. int
  336. support_fpu_underflow_control (int kind __attribute__((unused)))
  337. {
  338. return 0;
  339. }
  340. int
  341. get_fpu_underflow_mode (void)
  342. {
  343. return 0;
  344. }
  345. void
  346. set_fpu_underflow_mode (int gradual __attribute__((unused)))
  347. {
  348. }