fraiseexcpt.c 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /* Raise given exceptions.
  2. Copyright (C) 2013 Imagination Technologies Ltd.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; see the file COPYING.LIB. If
  14. not, see <http://www.gnu.org/licenses/>.  */
  15. #include <fenv.h>
  16. #include <math.h>
  17. libm_hidden_proto(feraiseexcept)
  18. int
  19. feraiseexcept (int excepts)
  20. {
  21. /* Raise exceptions represented by EXPECTS. But we must raise only
  22. one signal at a time. It is important that if the overflow/underflow
  23. exception and the inexact exception are given at the same time,
  24. the overflow/underflow exception follows the inexact exception. */
  25. /* First: invalid exception. */
  26. if ((FE_INVALID & excepts) != 0)
  27. {
  28. /* Reciprocal square root of a negative number is invalid. */
  29. __asm__ volatile(
  30. "F MOV FX.0,#0xc000 ! -2\n"
  31. "F RSQ FX.1,FX.0\n"
  32. );
  33. }
  34. /* Next: division by zero. */
  35. if ((FE_DIVBYZERO & excepts) != 0)
  36. {
  37. __asm__ volatile(
  38. "F MOV FX.0,#0\n"
  39. "F RCP FX.1,FX.0\n"
  40. );
  41. }
  42. /* Next: overflow. */
  43. if ((FE_OVERFLOW & excepts) != 0)
  44. {
  45. /* Adding a large number in single precision can cause overflow. */
  46. __asm__ volatile(
  47. " MOVT D0.0,#0x7f7f\n"
  48. " ADD D0.0,D0.0,#0xffff\n"
  49. "F MOV FX.0,D0.0\n"
  50. "F ADD FX.1,FX.0,FX.0\n"
  51. );
  52. }
  53. /* Next: underflow. */
  54. if ((FE_UNDERFLOW & excepts) != 0)
  55. {
  56. /* Multiplying a small value by 0.5 will cause an underflow. */
  57. __asm__ volatile(
  58. " MOV D0.0,#1\n"
  59. "F MOV FX.0,D0.0\n"
  60. " MOVT D0.0,#0x3f00\n"
  61. "F MOV FX.1,D0.0\n"
  62. "F MUL FX.2,FX.1,FX.0\n"
  63. );
  64. }
  65. /* Last: inexact. */
  66. if ((FE_INEXACT & excepts) != 0)
  67. {
  68. /* Converting a small single precision value to half precision
  69. can cause an inexact exception. */
  70. __asm__ volatile(
  71. " MOV D0.0,#0x0001\n"
  72. "F MOV FX.0,D0.0\n"
  73. "F FTOH FX.1,FX.0\n"
  74. );
  75. }
  76. /* Success. */
  77. return 0;
  78. }
  79. libm_hidden_def(feraiseexcept)