fpu-sysv.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. /* SysV FPU-related code (for systems not otherwise supported).
  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 SysV platforms with fpsetmask(). */
  21. /* BSD and Solaris systems have slightly different types and functions
  22. naming. We deal with these here, to simplify the code below. */
  23. #if HAVE_FP_EXCEPT
  24. # define FP_EXCEPT_TYPE fp_except
  25. #elif HAVE_FP_EXCEPT_T
  26. # define FP_EXCEPT_TYPE fp_except_t
  27. #else
  28. choke me
  29. #endif
  30. #if HAVE_FP_RND
  31. # define FP_RND_TYPE fp_rnd
  32. #elif HAVE_FP_RND_T
  33. # define FP_RND_TYPE fp_rnd_t
  34. #else
  35. choke me
  36. #endif
  37. #if HAVE_FPSETSTICKY
  38. # define FPSETSTICKY fpsetsticky
  39. #elif HAVE_FPRESETSTICKY
  40. # define FPSETSTICKY fpresetsticky
  41. #else
  42. choke me
  43. #endif
  44. void
  45. set_fpu_trap_exceptions (int trap, int notrap)
  46. {
  47. FP_EXCEPT_TYPE cw = fpgetmask();
  48. #ifdef FP_X_INV
  49. if (trap & GFC_FPE_INVALID)
  50. cw |= FP_X_INV;
  51. if (notrap & GFC_FPE_INVALID)
  52. cw &= ~FP_X_INV;
  53. #endif
  54. #ifdef FP_X_DNML
  55. if (trap & GFC_FPE_DENORMAL)
  56. cw |= FP_X_DNML;
  57. if (notrap & GFC_FPE_DENORMAL)
  58. cw &= ~FP_X_DNML;
  59. #endif
  60. #ifdef FP_X_DZ
  61. if (trap & GFC_FPE_ZERO)
  62. cw |= FP_X_DZ;
  63. if (notrap & GFC_FPE_ZERO)
  64. cw &= ~FP_X_DZ;
  65. #endif
  66. #ifdef FP_X_OFL
  67. if (trap & GFC_FPE_OVERFLOW)
  68. cw |= FP_X_OFL;
  69. if (notrap & GFC_FPE_OVERFLOW)
  70. cw &= ~FP_X_OFL;
  71. #endif
  72. #ifdef FP_X_UFL
  73. if (trap & GFC_FPE_UNDERFLOW)
  74. cw |= FP_X_UFL;
  75. if (notrap & GFC_FPE_UNDERFLOW)
  76. cw &= ~FP_X_UFL;
  77. #endif
  78. #ifdef FP_X_IMP
  79. if (trap & GFC_FPE_INEXACT)
  80. cw |= FP_X_IMP;
  81. if (notrap & GFC_FPE_INEXACT)
  82. cw &= ~FP_X_IMP;
  83. #endif
  84. fpsetmask(cw);
  85. }
  86. int
  87. get_fpu_trap_exceptions (void)
  88. {
  89. int res = 0;
  90. FP_EXCEPT_TYPE cw = fpgetmask();
  91. #ifdef FP_X_INV
  92. if (cw & FP_X_INV) res |= GFC_FPE_INVALID;
  93. #endif
  94. #ifdef FP_X_DNML
  95. if (cw & FP_X_DNML) res |= GFC_FPE_DENORMAL;
  96. #endif
  97. #ifdef FP_X_DZ
  98. if (cw & FP_X_DZ) res |= GFC_FPE_ZERO;
  99. #endif
  100. #ifdef FP_X_OFL
  101. if (cw & FP_X_OFL) res |= GFC_FPE_OVERFLOW;
  102. #endif
  103. #ifdef FP_X_UFL
  104. if (cw & FP_X_UFL) res |= GFC_FPE_UNDERFLOW;
  105. #endif
  106. #ifdef FP_X_IMP
  107. if (cw & FP_X_IMP) res |= GFC_FPE_INEXACT;
  108. #endif
  109. return res;
  110. }
  111. int
  112. support_fpu_trap (int flag)
  113. {
  114. return support_fpu_flag (flag);
  115. }
  116. void
  117. set_fpu (void)
  118. {
  119. #ifndef FP_X_INV
  120. if (options.fpe & GFC_FPE_INVALID)
  121. estr_write ("Fortran runtime warning: IEEE 'invalid operation' "
  122. "exception not supported.\n");
  123. #endif
  124. #ifndef FP_X_DNML
  125. if (options.fpe & GFC_FPE_DENORMAL)
  126. estr_write ("Fortran runtime warning: Floating point 'denormal operand' "
  127. "exception not supported.\n");
  128. #endif
  129. #ifndef FP_X_DZ
  130. if (options.fpe & GFC_FPE_ZERO)
  131. estr_write ("Fortran runtime warning: IEEE 'division by zero' "
  132. "exception not supported.\n");
  133. #endif
  134. #ifndef FP_X_OFL
  135. if (options.fpe & GFC_FPE_OVERFLOW)
  136. estr_write ("Fortran runtime warning: IEEE 'overflow' "
  137. "exception not supported.\n");
  138. #endif
  139. #ifndef FP_X_UFL
  140. if (options.fpe & GFC_FPE_UNDERFLOW)
  141. estr_write ("Fortran runtime warning: IEEE 'underflow' "
  142. "exception not supported.\n");
  143. #endif
  144. #ifndef FP_X_IMP
  145. if (options.fpe & GFC_FPE_INEXACT)
  146. estr_write ("Fortran runtime warning: IEEE 'inexact' "
  147. "exception not supported.\n");
  148. #endif
  149. set_fpu_trap_exceptions (options.fpe, 0);
  150. }
  151. int
  152. get_fpu_except_flags (void)
  153. {
  154. int result;
  155. FP_EXCEPT_TYPE set_excepts;
  156. result = 0;
  157. set_excepts = fpgetsticky ();
  158. #ifdef FP_X_INV
  159. if (set_excepts & FP_X_INV)
  160. result |= GFC_FPE_INVALID;
  161. #endif
  162. #ifdef FP_X_DZ
  163. if (set_excepts & FP_X_DZ)
  164. result |= GFC_FPE_ZERO;
  165. #endif
  166. #ifdef FP_X_OFL
  167. if (set_excepts & FP_X_OFL)
  168. result |= GFC_FPE_OVERFLOW;
  169. #endif
  170. #ifdef FP_X_UFL
  171. if (set_excepts & FP_X_UFL)
  172. result |= GFC_FPE_UNDERFLOW;
  173. #endif
  174. #ifdef FP_X_DNML
  175. if (set_excepts & FP_X_DNML)
  176. result |= GFC_FPE_DENORMAL;
  177. #endif
  178. #ifdef FP_X_IMP
  179. if (set_excepts & FP_X_IMP)
  180. result |= GFC_FPE_INEXACT;
  181. #endif
  182. return result;
  183. }
  184. void
  185. set_fpu_except_flags (int set, int clear)
  186. {
  187. FP_EXCEPT_TYPE flags;
  188. flags = fpgetsticky ();
  189. #ifdef FP_X_INV
  190. if (set & GFC_FPE_INVALID)
  191. flags |= FP_X_INV;
  192. if (clear & GFC_FPE_INVALID)
  193. flags &= ~FP_X_INV;
  194. #endif
  195. #ifdef FP_X_DZ
  196. if (set & GFC_FPE_ZERO)
  197. flags |= FP_X_DZ;
  198. if (clear & GFC_FPE_ZERO)
  199. flags &= ~FP_X_DZ;
  200. #endif
  201. #ifdef FP_X_OFL
  202. if (set & GFC_FPE_OVERFLOW)
  203. flags |= FP_X_OFL;
  204. if (clear & GFC_FPE_OVERFLOW)
  205. flags &= ~FP_X_OFL;
  206. #endif
  207. #ifdef FP_X_UFL
  208. if (set & GFC_FPE_UNDERFLOW)
  209. flags |= FP_X_UFL;
  210. if (clear & GFC_FPE_UNDERFLOW)
  211. flags &= ~FP_X_UFL;
  212. #endif
  213. #ifdef FP_X_DNML
  214. if (set & GFC_FPE_DENORMAL)
  215. flags |= FP_X_DNML;
  216. if (clear & GFC_FPE_DENORMAL)
  217. flags &= ~FP_X_DNML;
  218. #endif
  219. #ifdef FP_X_IMP
  220. if (set & GFC_FPE_INEXACT)
  221. flags |= FP_X_IMP;
  222. if (clear & GFC_FPE_INEXACT)
  223. flags &= ~FP_X_IMP;
  224. #endif
  225. FPSETSTICKY (flags);
  226. }
  227. int
  228. support_fpu_flag (int flag)
  229. {
  230. if (flag & GFC_FPE_INVALID)
  231. {
  232. #ifndef FP_X_INV
  233. return 0;
  234. #endif
  235. }
  236. else if (flag & GFC_FPE_ZERO)
  237. {
  238. #ifndef FP_X_DZ
  239. return 0;
  240. #endif
  241. }
  242. else if (flag & GFC_FPE_OVERFLOW)
  243. {
  244. #ifndef FP_X_OFL
  245. return 0;
  246. #endif
  247. }
  248. else if (flag & GFC_FPE_UNDERFLOW)
  249. {
  250. #ifndef FP_X_UFL
  251. return 0;
  252. #endif
  253. }
  254. else if (flag & GFC_FPE_DENORMAL)
  255. {
  256. #ifndef FP_X_DNML
  257. return 0;
  258. #endif
  259. }
  260. else if (flag & GFC_FPE_INEXACT)
  261. {
  262. #ifndef FP_X_IMP
  263. return 0;
  264. #endif
  265. }
  266. return 1;
  267. }
  268. int
  269. get_fpu_rounding_mode (void)
  270. {
  271. switch (fpgetround ())
  272. {
  273. case FP_RN:
  274. return GFC_FPE_TONEAREST;
  275. case FP_RP:
  276. return GFC_FPE_UPWARD;
  277. case FP_RM:
  278. return GFC_FPE_DOWNWARD;
  279. case FP_RZ:
  280. return GFC_FPE_TOWARDZERO;
  281. default:
  282. return 0; /* Should be unreachable. */
  283. }
  284. }
  285. void
  286. set_fpu_rounding_mode (int mode)
  287. {
  288. FP_RND_TYPE rnd_mode;
  289. switch (mode)
  290. {
  291. case GFC_FPE_TONEAREST:
  292. rnd_mode = FP_RN;
  293. break;
  294. case GFC_FPE_UPWARD:
  295. rnd_mode = FP_RP;
  296. break;
  297. case GFC_FPE_DOWNWARD:
  298. rnd_mode = FP_RM;
  299. break;
  300. case GFC_FPE_TOWARDZERO:
  301. rnd_mode = FP_RZ;
  302. break;
  303. default:
  304. return; /* Should be unreachable. */
  305. }
  306. fpsetround (rnd_mode);
  307. }
  308. int
  309. support_fpu_rounding_mode (int mode __attribute__((unused)))
  310. {
  311. return 1;
  312. }
  313. typedef struct
  314. {
  315. FP_EXCEPT_TYPE mask;
  316. FP_EXCEPT_TYPE sticky;
  317. FP_RND_TYPE round;
  318. } fpu_state_t;
  319. /* Check we can actually store the FPU state in the allocated size. */
  320. _Static_assert (sizeof(fpu_state_t) <= (size_t) GFC_FPE_STATE_BUFFER_SIZE,
  321. "GFC_FPE_STATE_BUFFER_SIZE is too small");
  322. void
  323. get_fpu_state (void *s)
  324. {
  325. fpu_state_t *state = s;
  326. state->mask = fpgetmask ();
  327. state->sticky = fpgetsticky ();
  328. state->round = fpgetround ();
  329. }
  330. void
  331. set_fpu_state (void *s)
  332. {
  333. fpu_state_t *state = s;
  334. fpsetmask (state->mask);
  335. FPSETSTICKY (state->sticky);
  336. fpsetround (state->round);
  337. }
  338. int
  339. support_fpu_underflow_control (int kind __attribute__((unused)))
  340. {
  341. return 0;
  342. }
  343. int
  344. get_fpu_underflow_mode (void)
  345. {
  346. return 0;
  347. }
  348. void
  349. set_fpu_underflow_mode (int gradual __attribute__((unused)))
  350. {
  351. }