Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
2.4 KiB

  1. /***
  2. *87except.c - floating point exception handling
  3. *
  4. * Copyright (c) 1991-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *
  8. *Revision History:
  9. * 8-24-91 GDP written
  10. * 9-26-91 GDP changed DOMAIN error handling
  11. * 1-29-91 GDP renamed to 87exept.c
  12. * 3-15-92 GDP support raising exceptions
  13. *
  14. *******************************************************************************/
  15. #include <errno.h>
  16. #include <math.h>
  17. #include <trans.h>
  18. #define _DOMAIN_QNAN 7 /* should be in sync with elem87.inc */
  19. #define _INEXACT 8 /* should be in sync with elem87.inc */
  20. int _matherr_flag;
  21. extern void _raise_exc(_FPIEEE_RECORD *prec,unsigned int *pcw,
  22. int flags, int opcode, double *parg1, double *presult);
  23. extern void _set_errno(int matherrtype);
  24. extern int _handle_exc(unsigned int flags, double * presult, unsigned int cw);
  25. /***
  26. *double _87except(struct _exception *except, unsigned int *cw)
  27. *
  28. *Purpose:
  29. * Handle floating point exceptions.
  30. *
  31. *Entry:
  32. *
  33. *Exit:
  34. *
  35. *Exceptions:
  36. *******************************************************************************/
  37. void _87except(int opcode, struct _exception *exc, unsigned short *pcw16)
  38. {
  39. int fixed;
  40. unsigned int flags;
  41. unsigned int cw, *pcw;
  42. //
  43. // convert fp control word into an unsigned int
  44. //
  45. cw = *pcw16;
  46. pcw = &cw;
  47. switch (exc->type) {
  48. case _DOMAIN:
  49. case _TLOSS:
  50. flags = FP_I;
  51. break;
  52. case _OVERFLOW:
  53. flags = FP_O | FP_P;
  54. break;
  55. case _UNDERFLOW:
  56. flags = FP_U | FP_P;
  57. break;
  58. case _SING:
  59. flags = FP_Z;
  60. break;
  61. case _INEXACT:
  62. flags = FP_P;
  63. break;
  64. case _DOMAIN_QNAN:
  65. exc->type = _DOMAIN;
  66. // no break
  67. default:
  68. flags = 0;
  69. }
  70. if (flags && _handle_exc(flags, &exc->retval, *pcw) == 0) {
  71. //
  72. // trap should be taken
  73. //
  74. _FPIEEE_RECORD rec;
  75. //
  76. // fill in operand2 info. The rest of rec will be
  77. // filled in by _raise_exc
  78. //
  79. switch (opcode) {
  80. case OP_POW:
  81. case OP_FMOD:
  82. case OP_ATAN2:
  83. rec.Operand2.OperandValid = 1;
  84. rec.Operand2.Format = _FpFormatFp64;
  85. rec.Operand2.Value.Fp64Value = exc->arg2;
  86. break;
  87. default:
  88. rec.Operand2.OperandValid = 0;
  89. }
  90. _raise_exc(&rec,
  91. pcw,
  92. flags,
  93. opcode,
  94. &exc->arg1,
  95. &exc->retval);
  96. }
  97. /* restore cw */
  98. _rstorfp(*pcw);
  99. fixed = 0;
  100. if (exc->type != _INEXACT &&
  101. ! _matherr_flag) {
  102. fixed = _matherr(exc);
  103. }
  104. if (!fixed) {
  105. _set_errno(exc->type);
  106. }
  107. }