FPcontrol-Irix.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /* Load programs with -lfpe. See man pages for fpc and /usr/include/sigfpe.h, sys/fpu.h. */
  2. #include <stdlib.h>
  3. #include <sigfpe.h>
  4. #include <sys/fpu.h>
  5. typedef unsigned int ulong;
  6. #include "mathi.h"
  7. /*
  8. * Irix does not permit a use handled SIGFPE since the floating point unit
  9. * cannot be IEEE754 compliant without some software, so we must vector using
  10. * the library
  11. */
  12. extern void trapFPE(unsigned exception[5], int value[2]);
  13. void
  14. FPinit(void)
  15. {
  16. union fpc_csr csr;
  17. int i;
  18. for(i=1; i<=4; i++) {
  19. sigfpe_[i].repls = _USER_DETERMINED;
  20. sigfpe_[i].abort = 2;
  21. }
  22. handle_sigfpes(_ON,
  23. _EN_UNDERFL|_EN_OVERFL|_EN_DIVZERO|_EN_INVALID,
  24. trapFPE,
  25. _ABORT_ON_ERROR, 0);
  26. }
  27. ulong
  28. getFPstatus(void)
  29. {
  30. ulong fsr = 0;
  31. union fpc_csr csr;
  32. csr.fc_word = get_fpc_csr();
  33. if(csr.fc_struct.se_inexact) fsr |= INEX;
  34. if(csr.fc_struct.se_overflow) fsr |= OVFL;
  35. if(csr.fc_struct.se_underflow) fsr |= UNFL;
  36. if(csr.fc_struct.se_divide0) fsr |= ZDIV;
  37. if(csr.fc_struct.se_invalid) fsr |= INVAL;
  38. return fsr;
  39. }
  40. ulong
  41. FPstatus(ulong fsr, ulong mask)
  42. {
  43. ulong old = getFPstatus();
  44. union fpc_csr csr;
  45. csr.fc_word = get_fpc_csr();
  46. fsr = (fsr&mask) | (old&~mask);
  47. csr.fc_struct.se_inexact = (fsr&INEX)?1:0;
  48. csr.fc_struct.se_overflow = (fsr&OVFL)?1:0;
  49. csr.fc_struct.se_underflow = (fsr&UNFL)?1:0;
  50. csr.fc_struct.se_divide0 = (fsr&ZDIV)?1:0;
  51. csr.fc_struct.se_invalid = (fsr&INVAL)?1:0;
  52. set_fpc_csr(csr.fc_word);
  53. return(old&mask);
  54. }
  55. ulong
  56. getFPcontrol(void)
  57. {
  58. ulong fcr = 0;
  59. union fpc_csr csr;
  60. double junk = fabs(1.); /* avoid bug mentioned in sigfpes man page [ehg] */
  61. csr.fc_word = get_fpc_csr();
  62. switch(csr.fc_struct.rounding_mode){
  63. case ROUND_TO_NEAREST: fcr = RND_NR; break;
  64. case ROUND_TO_MINUS_INFINITY: fcr = RND_NINF; break;
  65. case ROUND_TO_PLUS_INFINITY: fcr = RND_PINF; break;
  66. case ROUND_TO_ZERO: fcr = RND_Z; break;
  67. }
  68. if(csr.fc_struct.en_inexact) fcr |= INEX;
  69. if(csr.fc_struct.en_overflow) fcr |= OVFL;
  70. if(csr.fc_struct.en_underflow) fcr |= UNFL;
  71. if(csr.fc_struct.en_divide0) fcr |= ZDIV;
  72. if(csr.fc_struct.en_invalid) fcr |= INVAL;
  73. return fcr;
  74. }
  75. ulong
  76. FPcontrol(ulong fcr, ulong mask)
  77. {
  78. ulong old = getFPcontrol();
  79. union fpc_csr csr;
  80. csr.fc_word = get_fpc_csr();
  81. fcr = (fcr&mask) | (old&~mask);
  82. csr.fc_struct.en_inexact = (fcr&INEX)?1:0;
  83. csr.fc_struct.en_overflow = (fcr&OVFL)?1:0;
  84. csr.fc_struct.en_underflow = (fcr&UNFL)?1:0;
  85. csr.fc_struct.en_divide0 = (fcr&ZDIV)?1:0;
  86. csr.fc_struct.en_invalid = (fcr&INVAL)?1:0;
  87. switch(fcr&RND_MASK){
  88. case RND_NR: csr.fc_struct.rounding_mode = ROUND_TO_NEAREST; break;
  89. case RND_NINF: csr.fc_struct.rounding_mode = ROUND_TO_MINUS_INFINITY; break;
  90. case RND_PINF: csr.fc_struct.rounding_mode = ROUND_TO_PLUS_INFINITY; break;
  91. case RND_Z: csr.fc_struct.rounding_mode = ROUND_TO_ZERO; break;
  92. }
  93. set_fpc_csr(csr.fc_word);
  94. return(old&mask);
  95. }