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.

302 lines
4.5 KiB

  1. /***
  2. *ieee.c - ieee control and status routines
  3. *
  4. * Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * IEEE control and status routines.
  8. *
  9. *Revision History:
  10. *
  11. * 04-01-02 GDP Rewritten to use abstract control and status words
  12. *
  13. */
  14. #include <trans.h>
  15. #include <float.h>
  16. static unsigned int _abstract_sw(unsigned short sw);
  17. static unsigned int _abstract_cw(unsigned short cw);
  18. static unsigned short _hw_cw(unsigned int abstr);
  19. /***
  20. * _statusfp() -
  21. *
  22. *Purpose:
  23. * return abstract fp status word
  24. *
  25. *Entry:
  26. *
  27. *Exit:
  28. *
  29. *Exceptions:
  30. *
  31. *******************************************************************************/
  32. unsigned int _statusfp()
  33. {
  34. short status;
  35. _asm {
  36. fstsw status
  37. }
  38. return _abstract_sw(status);
  39. }
  40. /***
  41. *_clearfp() -
  42. *
  43. *Purpose:
  44. * return abstract status word and clear status
  45. *
  46. *Entry:
  47. *
  48. *Exit:
  49. *
  50. *Exceptions:
  51. *
  52. *******************************************************************************/
  53. unsigned int _clearfp()
  54. {
  55. short status;
  56. _asm {
  57. fnstsw status
  58. fnclex
  59. }
  60. return _abstract_sw(status);
  61. }
  62. /*** _controlfp
  63. *() -
  64. *
  65. *Purpose:
  66. * return and set abstract user fp control word
  67. *
  68. *Entry:
  69. *
  70. *Exit:
  71. *
  72. *Exceptions:
  73. *
  74. *******************************************************************************/
  75. unsigned int _controlfp(unsigned int newctrl, unsigned int mask)
  76. {
  77. short oldCw;
  78. short newCw;
  79. unsigned int oldabs;
  80. unsigned int newabs;
  81. _asm {
  82. fstcw oldCw
  83. }
  84. oldabs = _abstract_cw(oldCw);
  85. newabs = (newctrl & mask) | (oldabs & ~mask);
  86. newCw = _hw_cw(newabs);
  87. _asm {
  88. fldcw newCw
  89. }
  90. return newabs;
  91. } /* _controlfp() */
  92. /***
  93. * _abstract_cw() - abstract control word
  94. *
  95. *Purpose:
  96. * produce a fp control word in abstracted (machine independent) form
  97. *
  98. *Entry:
  99. * cw: machine control word
  100. *
  101. *Exit:
  102. *
  103. *Exceptions:
  104. *
  105. *******************************************************************************/
  106. unsigned int _abstract_cw(unsigned short cw)
  107. {
  108. unsigned int abstr = 0;
  109. //
  110. // Set exception mask bits
  111. //
  112. if (cw & IEM_INVALID)
  113. abstr |= _EM_INVALID;
  114. if (cw & IEM_ZERODIVIDE)
  115. abstr |= _EM_ZERODIVIDE;
  116. if (cw & IEM_OVERFLOW)
  117. abstr |= _EM_OVERFLOW;
  118. if (cw & IEM_UNDERFLOW)
  119. abstr |= _EM_UNDERFLOW;
  120. if (cw & IEM_INEXACT)
  121. abstr |= _EM_INEXACT;
  122. //
  123. // Set rounding mode
  124. //
  125. switch (cw & IMCW_RC) {
  126. case IRC_NEAR:
  127. abstr |= _RC_NEAR;
  128. break;
  129. case IRC_UP:
  130. abstr |= _RC_UP;
  131. break;
  132. case IRC_DOWN:
  133. abstr |= _RC_DOWN;
  134. break;
  135. case IRC_CHOP:
  136. abstr |= _RC_CHOP;
  137. break;
  138. }
  139. //
  140. // Set Precision mode
  141. //
  142. switch (cw & IMCW_PC) {
  143. case IPC_64:
  144. abstr |= _PC_64;
  145. break;
  146. case IPC_53:
  147. abstr |= _PC_53;
  148. break;
  149. case IPC_24:
  150. abstr |= _PC_24;
  151. break;
  152. }
  153. return abstr;
  154. }
  155. /***
  156. * _hw_cw() - h/w control word
  157. *
  158. *Purpose:
  159. * produce a machine dependent fp control word
  160. *
  161. *
  162. *Entry:
  163. * abstr: abstract control word
  164. *
  165. *Exit:
  166. *
  167. *Exceptions:
  168. *
  169. *******************************************************************************/
  170. unsigned short _hw_cw(unsigned int abstr)
  171. {
  172. //
  173. // Set standard infinity and denormal control bits
  174. //
  175. unsigned short cw = 0x1002;
  176. //
  177. // Set exception mask bits
  178. //
  179. if (abstr & _EM_INVALID)
  180. cw |= IEM_INVALID;
  181. if (abstr & _EM_ZERODIVIDE)
  182. cw |= IEM_ZERODIVIDE;
  183. if (abstr & _EM_OVERFLOW)
  184. cw |= IEM_OVERFLOW;
  185. if (abstr & _EM_UNDERFLOW)
  186. cw |= IEM_UNDERFLOW;
  187. if (abstr & _EM_INEXACT)
  188. cw |= IEM_INEXACT;
  189. //
  190. // Set rounding mode
  191. //
  192. switch (abstr & _MCW_RC) {
  193. case _RC_NEAR:
  194. cw |= IRC_NEAR;
  195. break;
  196. case _RC_UP:
  197. cw |= IRC_UP;
  198. break;
  199. case _RC_DOWN:
  200. cw |= IRC_DOWN;
  201. break;
  202. case _RC_CHOP:
  203. cw |= IRC_CHOP;
  204. break;
  205. }
  206. //
  207. // Set Precision mode
  208. //
  209. switch (abstr & _MCW_PC) {
  210. case _PC_64:
  211. cw |= IPC_64;
  212. break;
  213. case _PC_53:
  214. cw |= IPC_53;
  215. break;
  216. case _PC_24:
  217. cw |= IPC_24;
  218. break;
  219. }
  220. return cw;
  221. }
  222. /***
  223. * _abstract_sw() - abstract fp status word
  224. *
  225. *Purpose:
  226. * produce an abstract (machine independent) fp status word
  227. *
  228. *
  229. *Entry:
  230. * sw: machine status word
  231. *
  232. *Exit:
  233. *
  234. *Exceptions:
  235. *
  236. *******************************************************************************/
  237. unsigned int _abstract_sw(unsigned short sw)
  238. {
  239. unsigned int abstr = 0;
  240. if (sw & ISW_INVALID)
  241. abstr |= _EM_INVALID;
  242. if (sw & ISW_ZERODIVIDE)
  243. abstr |= _EM_ZERODIVIDE;
  244. if (sw & ISW_OVERFLOW)
  245. abstr |= _EM_OVERFLOW;
  246. if (sw & ISW_UNDERFLOW)
  247. abstr |= _EM_UNDERFLOW;
  248. if (sw & ISW_INEXACT)
  249. abstr |= _EM_INEXACT;
  250. return abstr;
  251. }