fraiseexcpt.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /* Raise given exceptions.
  2. Copyright (C) 2018-2025 Free Software Foundation, Inc.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library. If not, see
  13. <https://www.gnu.org/licenses/>. */
  14. #include <fenv.h>
  15. #include "fenv_libc.h"
  16. #include <fpu_control.h>
  17. #include <float.h>
  18. #include <math.h>
  19. int
  20. feraiseexcept (int excepts)
  21. {
  22. /* Raise exceptions represented by EXCEPTS. But we must raise only one
  23. signal at a time. It is important that if the overflow/underflow
  24. exception and the divide by zero exception are given at the same
  25. time, the overflow/underflow exception follows the divide by zero
  26. exception. */
  27. # ifndef __csky_fpuv1__
  28. /* First: invalid exception. */
  29. if (FE_INVALID & excepts)
  30. {
  31. /* One example of a invalid operation is 0 * Infinity. */
  32. float x = HUGE_VALF, y = 0.0f;
  33. __asm__ __volatile__ ("fmuls %0, %0, %1" : "+v" (x) : "v" (y));
  34. }
  35. /* Next: division by zero. */
  36. if (FE_DIVBYZERO & excepts)
  37. {
  38. float x = 1.0f, y = 0.0f;
  39. __asm__ __volatile__ ("fdivs %0, %0, %1" : "+v" (x) : "v" (y));
  40. }
  41. /* Next: overflow. */
  42. if (FE_OVERFLOW & excepts)
  43. {
  44. float x = FLT_MAX;
  45. __asm__ __volatile__ ("fmuls %0, %0, %0" : "+v" (x));
  46. }
  47. /* Next: underflow. */
  48. if (FE_UNDERFLOW & excepts)
  49. {
  50. float x = -FLT_MIN;
  51. __asm__ __volatile__ ("fmuls %0, %0, %0" : "+v" (x));
  52. }
  53. /* Last: inexact. */
  54. if (FE_INEXACT & excepts)
  55. {
  56. float x = 1.0f, y = 3.0f;
  57. __asm__ __volatile__ ("fdivs %0, %0, %1" : "+v" (x) : "v" (y));
  58. }
  59. if (__FE_DENORMAL & excepts)
  60. {
  61. double x = 4.9406564584124654e-324;
  62. __asm__ __volatile__ ("fstod %0, %0" : "+v" (x));
  63. }
  64. # else
  65. int tmp = 0;
  66. /* First: invalid exception. */
  67. if (FE_INVALID & excepts)
  68. {
  69. /* One example of a invalid operation is 0 * Infinity. */
  70. float x = HUGE_VALF, y = 0.0f;
  71. __asm__ __volatile__ ("fmuls %0, %0, %2, %1"
  72. : "+f" (x), "+r"(tmp) : "f" (y));
  73. }
  74. /* Next: division by zero. */
  75. if (FE_DIVBYZERO & excepts)
  76. {
  77. float x = 1.0f, y = 0.0f;
  78. __asm__ __volatile__ ("fdivs %0, %0, %2, %1"
  79. : "+f" (x), "+r"(tmp) : "f" (y));
  80. }
  81. /* Next: overflow. */
  82. if (FE_OVERFLOW & excepts)
  83. {
  84. float x = FLT_MAX, y = FLT_MAX;
  85. __asm__ __volatile__ ("fmuls %0, %0, %2, %1"
  86. : "+f" (x), "+r"(tmp) : "f" (y));
  87. }
  88. /* Next: underflow. */
  89. if (FE_UNDERFLOW & excepts)
  90. {
  91. float x = -FLT_MIN, y = -FLT_MIN;
  92. __asm__ __volatile__ ("fmuls %0, %0, %2, %1"
  93. : "+f" (x), "+r"(tmp) : "f" (y));
  94. }
  95. /* Last: inexact. */
  96. if (FE_INEXACT & excepts)
  97. {
  98. float x = 1.0f, y = 3.0f;
  99. __asm__ __volatile__ ("fdivs %0, %0, %2, %1"
  100. : "+f" (x), "+r"(tmp) : "f" (y));
  101. }
  102. # endif /* __csky_fpuv2__ */
  103. /* Success. */
  104. return 0;
  105. }