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.

166 lines
2.4 KiB

  1. /***
  2. *fpctrl.c - fp low level control and status routines
  3. *
  4. * Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * IEEE control and status routines for internal use.
  8. * These routines use machine specific constants while _controlfp,
  9. * _statusfp, and _clearfp use an abstracted control/status word
  10. *
  11. *Revision History:
  12. *
  13. * 03-31-92 GDP written
  14. * 05-12-92 GJF Rewrote fdivr as fdivrp st(1),st to work around C8-32
  15. * assertions.
  16. *
  17. */
  18. #include <trans.h>
  19. /*** _statfp
  20. *() -
  21. *
  22. *Purpose:
  23. * return user status word
  24. *
  25. *Entry:
  26. *
  27. *Exit:
  28. *
  29. *Exceptions:
  30. *
  31. *******************************************************************************/
  32. unsigned int _statfp()
  33. {
  34. short status;
  35. _asm {
  36. fstsw status
  37. }
  38. return status;
  39. }
  40. /*** _clrfp
  41. *() -
  42. *
  43. *Purpose:
  44. * return user status word and clear status
  45. *
  46. *Entry:
  47. *
  48. *Exit:
  49. *
  50. *Exceptions:
  51. *
  52. *******************************************************************************/
  53. unsigned int _clrfp()
  54. {
  55. short status;
  56. _asm {
  57. fnstsw status
  58. fnclex
  59. }
  60. return status;
  61. }
  62. /*** _ctrlfp
  63. *() -
  64. *
  65. *Purpose:
  66. * return and set user control word
  67. *
  68. *Entry:
  69. *
  70. *Exit:
  71. *
  72. *Exceptions:
  73. *
  74. *******************************************************************************/
  75. unsigned int _ctrlfp(unsigned int newctrl, unsigned int _mask)
  76. {
  77. short oldCw;
  78. short newCw;
  79. _asm {
  80. fstcw oldCw
  81. }
  82. newCw = (short) ((newctrl & _mask) | (oldCw & ~_mask));
  83. _asm {
  84. fldcw newCw
  85. }
  86. return oldCw;
  87. }
  88. /*** _set_statfp
  89. *() -
  90. *
  91. *Purpose:
  92. * force selected exception flags to 1
  93. *
  94. *Entry:
  95. *
  96. *Exit:
  97. *
  98. *Exceptions:
  99. *
  100. *******************************************************************************/
  101. static unsigned long over[3] = { 0x0, 0x80000000, 0x4410 };
  102. static unsigned long under[3] = { 0x1, 0x80000000, 0x3000 };
  103. void _set_statfp(unsigned int sw)
  104. {
  105. int itmp;
  106. double tmp;
  107. if (sw & ISW_INVALID) {
  108. _asm {
  109. fld tbyte ptr over
  110. fistp itmp
  111. fwait
  112. }
  113. }
  114. if (sw & ISW_OVERFLOW) { // will also trigger precision
  115. _asm {
  116. fstsw ax
  117. fld tbyte ptr over
  118. fstp tmp
  119. fwait
  120. fstsw ax
  121. }
  122. }
  123. if (sw & ISW_UNDERFLOW) { // will also trigger precision
  124. _asm {
  125. fld tbyte ptr under
  126. fstp tmp
  127. fwait
  128. }
  129. }
  130. if (sw & ISW_ZERODIVIDE) {
  131. _asm {
  132. fldz
  133. fld1
  134. fdivrp st(1), st
  135. fstp st(0)
  136. fwait
  137. }
  138. }
  139. if (sw & ISW_INEXACT) {
  140. _asm {
  141. fldpi
  142. fstp tmp
  143. fwait
  144. }
  145. }
  146. }