ieee_helper.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /* Helper functions in C for IEEE modules
  2. Copyright (C) 2013-2015 Free Software Foundation, Inc.
  3. Contributed by Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
  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. #include "libgfortran.h"
  21. /* Prototypes. */
  22. extern int ieee_class_helper_4 (GFC_REAL_4 *);
  23. internal_proto(ieee_class_helper_4);
  24. extern int ieee_class_helper_8 (GFC_REAL_8 *);
  25. internal_proto(ieee_class_helper_8);
  26. /* Enumeration of the possible floating-point types. These values
  27. correspond to the hidden arguments of the IEEE_CLASS_TYPE
  28. derived-type of IEEE_ARITHMETIC. */
  29. enum { IEEE_OTHER_VALUE = 0, IEEE_SIGNALING_NAN, IEEE_QUIET_NAN,
  30. IEEE_NEGATIVE_INF, IEEE_NEGATIVE_NORMAL, IEEE_NEGATIVE_DENORMAL,
  31. IEEE_NEGATIVE_ZERO, IEEE_POSITIVE_ZERO, IEEE_POSITIVE_DENORMAL,
  32. IEEE_POSITIVE_NORMAL, IEEE_POSITIVE_INF };
  33. #define CLASSMACRO(TYPE) \
  34. int ieee_class_helper_ ## TYPE (GFC_REAL_ ## TYPE *value) \
  35. { \
  36. int res = __builtin_fpclassify (IEEE_QUIET_NAN, IEEE_POSITIVE_INF, \
  37. IEEE_POSITIVE_NORMAL, \
  38. IEEE_POSITIVE_DENORMAL, \
  39. IEEE_POSITIVE_ZERO, *value); \
  40. \
  41. if (__builtin_signbit (*value)) \
  42. { \
  43. if (res == IEEE_POSITIVE_NORMAL) \
  44. return IEEE_NEGATIVE_NORMAL; \
  45. else if (res == IEEE_POSITIVE_DENORMAL) \
  46. return IEEE_NEGATIVE_DENORMAL; \
  47. else if (res == IEEE_POSITIVE_ZERO) \
  48. return IEEE_NEGATIVE_ZERO; \
  49. else if (res == IEEE_POSITIVE_INF) \
  50. return IEEE_NEGATIVE_INF; \
  51. } \
  52. \
  53. if (res == IEEE_QUIET_NAN) \
  54. { \
  55. /* TODO: Handle signaling NaNs */ \
  56. return res; \
  57. } \
  58. \
  59. return res; \
  60. }
  61. CLASSMACRO(4)
  62. CLASSMACRO(8)
  63. #define GFC_FPE_ALL (GFC_FPE_INVALID | GFC_FPE_DENORMAL | \
  64. GFC_FPE_ZERO | GFC_FPE_OVERFLOW | \
  65. GFC_FPE_UNDERFLOW | GFC_FPE_INEXACT)
  66. /* Functions to save and restore floating-point state, clear and restore
  67. exceptions on procedure entry/exit. The rules we follow are set
  68. in Fortran 2008's 14.3 paragraph 3, note 14.4, 14.4 paragraph 4,
  69. 14.5 paragraph 2, and 14.6 paragraph 1. */
  70. void ieee_procedure_entry (void *);
  71. export_proto(ieee_procedure_entry);
  72. void
  73. ieee_procedure_entry (void *state)
  74. {
  75. /* Save the floating-point state in the space provided by the caller. */
  76. get_fpu_state (state);
  77. /* Clear the floating-point exceptions. */
  78. set_fpu_except_flags (0, GFC_FPE_ALL);
  79. }
  80. void ieee_procedure_exit (void *);
  81. export_proto(ieee_procedure_exit);
  82. void
  83. ieee_procedure_exit (void *state)
  84. {
  85. /* Get the flags currently signaling. */
  86. int flags = get_fpu_except_flags ();
  87. /* Restore the floating-point state we had on entry. */
  88. set_fpu_state (state);
  89. /* And re-raised the flags that were raised since entry. */
  90. set_fpu_except_flags (flags, 0);
  91. }