Leaked source code of windows server 2003
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.

333 lines
6.0 KiB

  1. /***
  2. *ieee.c - ieee control and status routines
  3. *
  4. * Copyright (c) 1985-2000, Microsoft Corporation
  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. #include <signal.h>
  17. extern unsigned int _get_fpsr(void);
  18. extern void _set_fpsr(unsigned int);
  19. extern void _fclrf(void);
  20. static unsigned int _abstract_sw(unsigned int sw);
  21. static unsigned int _abstract_cw(unsigned int cw);
  22. static unsigned int _hw_cw(unsigned int abstr);
  23. #define FS (1<<6)
  24. /***
  25. * _statusfp() -
  26. *
  27. *Purpose:
  28. * return abstract fp status word
  29. *
  30. *Entry:
  31. *
  32. *Exit:
  33. *
  34. *Exceptions:
  35. *
  36. *******************************************************************************/
  37. unsigned int _statusfp()
  38. {
  39. unsigned int status;
  40. status = _get_fpsr();
  41. return _abstract_sw(status);
  42. }
  43. /***
  44. *_clearfp() -
  45. *
  46. *Purpose:
  47. * return abstract status word and clear status
  48. *
  49. *Entry:
  50. *
  51. *Exit:
  52. *
  53. *Exceptions:
  54. *
  55. *******************************************************************************/
  56. unsigned int _clearfp()
  57. {
  58. unsigned int status;
  59. status = _get_fpsr();
  60. _fclrf();
  61. return _abstract_sw(status);
  62. }
  63. /*** _control87
  64. *() -
  65. *
  66. *Purpose:
  67. * return and set abstract user fp control word
  68. * can modify EM_DENORMAL mask
  69. *
  70. *Entry:
  71. *
  72. *Exit:
  73. *
  74. *Exceptions:
  75. *
  76. *******************************************************************************/
  77. unsigned int _control87(unsigned int newctrl, unsigned int mask)
  78. {
  79. unsigned int oldCw;
  80. unsigned int newCw;
  81. unsigned int oldabs;
  82. unsigned int newabs;
  83. oldCw = _get_fpsr();
  84. oldabs = _abstract_cw(oldCw);
  85. newabs = (newctrl & mask) | (oldabs & ~mask);
  86. newCw = _hw_cw(newabs);
  87. _set_fpsr(newCw);
  88. return newabs;
  89. } /* _control87() */
  90. /*** _controlfp
  91. *() -
  92. *
  93. *Purpose:
  94. * return and set abstract user fp control word
  95. * cannot change denormal mask (ignores _EM_DENORMAL)
  96. * This is done for portable IEEE behavior on all platforms
  97. *
  98. *Entry:
  99. *
  100. *Exit:
  101. *
  102. *Exceptions:
  103. *
  104. *******************************************************************************/
  105. unsigned int _controlfp(unsigned int newctrl, unsigned int mask)
  106. {
  107. return _control87(newctrl, mask & ~_EM_DENORMAL);
  108. }
  109. /***
  110. * _abstract_cw() - abstract control word
  111. *
  112. *Purpose:
  113. * produce a fp control word in abstracted (machine independent) form
  114. *
  115. *Entry:
  116. * cw: machine control word
  117. *
  118. *Exit:
  119. *
  120. *Exceptions:
  121. *
  122. *******************************************************************************/
  123. unsigned int _abstract_cw(unsigned int cw)
  124. {
  125. unsigned int abstr = 0;
  126. //
  127. // Set exception mask bits
  128. //
  129. if (cw & IEM_INVALID)
  130. abstr |= _EM_INVALID;
  131. if (cw & IEM_ZERODIVIDE)
  132. abstr |= _EM_ZERODIVIDE;
  133. if (cw & IEM_OVERFLOW)
  134. abstr |= _EM_OVERFLOW;
  135. if (cw & IEM_UNDERFLOW)
  136. abstr |= _EM_UNDERFLOW;
  137. if (cw & IEM_INEXACT)
  138. abstr |= _EM_INEXACT;
  139. if (cw & IEM_DENORMAL)
  140. abstr |= _EM_DENORMAL;
  141. //
  142. // Set rounding mode
  143. //
  144. switch (cw & IMCW_RC) {
  145. case IRC_NEAR:
  146. abstr |= _RC_NEAR;
  147. break;
  148. case IRC_UP:
  149. abstr |= _RC_UP;
  150. break;
  151. case IRC_DOWN:
  152. abstr |= _RC_DOWN;
  153. break;
  154. case IRC_CHOP:
  155. abstr |= _RC_CHOP;
  156. break;
  157. }
  158. return abstr;
  159. }
  160. /***
  161. * _hw_cw() - h/w control word
  162. *
  163. *Purpose:
  164. * produce a machine dependent fp control word
  165. *
  166. *
  167. *Entry:
  168. * abstr: abstract control word
  169. *
  170. *Exit:
  171. *
  172. *Exceptions:
  173. *
  174. *******************************************************************************/
  175. unsigned int _hw_cw(unsigned int abstr)
  176. {
  177. //
  178. // Set standard infinity and denormal control bits
  179. //
  180. unsigned int cw = 0;
  181. //
  182. // Set exception mask bits
  183. //
  184. if (abstr & _EM_INVALID)
  185. cw |= IEM_INVALID;
  186. if (abstr & _EM_ZERODIVIDE)
  187. cw |= IEM_ZERODIVIDE;
  188. if (abstr & _EM_OVERFLOW)
  189. cw |= IEM_OVERFLOW;
  190. if (abstr & _EM_UNDERFLOW)
  191. cw |= IEM_UNDERFLOW;
  192. if (abstr & _EM_INEXACT)
  193. cw |= IEM_INEXACT;
  194. if (abstr & _EM_DENORMAL)
  195. cw |= IEM_DENORMAL;
  196. //
  197. // Set rounding mode
  198. //
  199. switch (abstr & _MCW_RC) {
  200. case _RC_NEAR:
  201. cw |= IRC_NEAR;
  202. break;
  203. case _RC_UP:
  204. cw |= IRC_UP;
  205. break;
  206. case _RC_DOWN:
  207. cw |= IRC_DOWN;
  208. break;
  209. case _RC_CHOP:
  210. cw |= IRC_CHOP;
  211. break;
  212. }
  213. return cw;
  214. }
  215. /***
  216. * _abstract_sw() - abstract fp status word
  217. *
  218. *Purpose:
  219. * produce an abstract (machine independent) fp status word
  220. *
  221. *
  222. *Entry:
  223. * sw: machine status word
  224. *
  225. *Exit:
  226. *
  227. *Exceptions:
  228. *
  229. *******************************************************************************/
  230. unsigned int _abstract_sw(unsigned int sw)
  231. {
  232. unsigned int abstr = 0;
  233. if (sw & ISW_INVALID)
  234. abstr |= _SW_INVALID;
  235. if (sw & ISW_ZERODIVIDE)
  236. abstr |= _SW_ZERODIVIDE;
  237. if (sw & ISW_OVERFLOW)
  238. abstr |= _SW_OVERFLOW;
  239. if (sw & ISW_UNDERFLOW)
  240. abstr |= _SW_UNDERFLOW;
  241. if (sw & ISW_INEXACT)
  242. abstr |= _SW_INEXACT;
  243. if (sw & ISW_DENORMAL)
  244. abstr |= _SW_DENORMAL;
  245. return abstr;
  246. }
  247. /***
  248. * _fpreset() - reset fp system
  249. *
  250. *Purpose:
  251. * reset fp environment to the default state
  252. * Also reset saved fp environment if invoked from a user's
  253. * signal handler
  254. *
  255. *Entry:
  256. *
  257. *Exit:
  258. *
  259. *Exceptions:
  260. *
  261. *******************************************************************************/
  262. void _fpreset()
  263. {
  264. unsigned int status = ICW;
  265. // PEXCEPTION_POINTERS excptrs = (PEXCEPTION_POINTERS) _pxcptinfoptrs;
  266. //
  267. // reset fp state
  268. //
  269. _set_fpsr(status);
  270. // if (excptrs &&
  271. // excptrs->ContextRecord->ContextFlags & CONTEXT_FLOATING_POINT) {
  272. // _fpreset has been invoked by a signal handler which in turn
  273. // has been invoked by the CRT filter routine. In this case
  274. // the saved fp context should be cleared, so that the change take
  275. // effect on continuation.
  276. // excptrs->ContextRecord->StFPSR = ICW;
  277. // }
  278. }