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.

406 lines
7.6 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. * 10-30-92 GDP _fpreset now resets saved fp context if called from a
  13. * signal handler.
  14. * 09-01-94 SKS Change include file from <nt.h> to <windows.h>
  15. * 04-11-95 JWM _fpreset() now resets default precision.
  16. * 05-10-96 BWT Fix POSIX build.
  17. *
  18. */
  19. #include <trans.h>
  20. #include <float.h>
  21. #include <windows.h>
  22. #include <signal.h>
  23. extern void _setdefaultprecision();
  24. static unsigned int _abstract_sw(unsigned short sw);
  25. static unsigned int _abstract_cw(unsigned short cw);
  26. static unsigned short _hw_cw(unsigned int abstr);
  27. /***
  28. * _statusfp() -
  29. *
  30. *Purpose:
  31. * return abstract fp status word
  32. *
  33. *Entry:
  34. *
  35. *Exit:
  36. *
  37. *Exceptions:
  38. *
  39. *******************************************************************************/
  40. unsigned int _statusfp()
  41. {
  42. short status;
  43. _asm {
  44. fstsw status
  45. }
  46. return _abstract_sw(status);
  47. }
  48. /***
  49. *_clearfp() -
  50. *
  51. *Purpose:
  52. * return abstract status word and clear status
  53. *
  54. *Entry:
  55. *
  56. *Exit:
  57. *
  58. *Exceptions:
  59. *
  60. *******************************************************************************/
  61. unsigned int _clearfp()
  62. {
  63. short status;
  64. _asm {
  65. fnstsw status
  66. fnclex
  67. }
  68. return _abstract_sw(status);
  69. }
  70. /*** _control87
  71. *() -
  72. *
  73. *Purpose:
  74. * return and set abstract user fp control word
  75. * can modify EM_DENORMAL mask
  76. *
  77. *Entry:
  78. *
  79. *Exit:
  80. *
  81. *Exceptions:
  82. *
  83. *******************************************************************************/
  84. unsigned int _control87(unsigned int newctrl, unsigned int mask)
  85. {
  86. short oldCw;
  87. short newCw;
  88. unsigned int oldabs;
  89. unsigned int newabs;
  90. _asm {
  91. fstcw oldCw
  92. }
  93. oldabs = _abstract_cw(oldCw);
  94. newabs = (newctrl & mask) | (oldabs & ~mask);
  95. newCw = _hw_cw(newabs);
  96. _asm {
  97. fldcw newCw
  98. }
  99. return newabs;
  100. } /* _controlfp() */
  101. /*** _controlfp
  102. *() -
  103. *
  104. *Purpose:
  105. * return and set abstract user fp control word
  106. * cannot change denormal mask (ignores _EM_DENORMAL)
  107. * This is done for portable IEEE behavior on all platforms
  108. *
  109. *Entry:
  110. *
  111. *Exit:
  112. *
  113. *Exceptions:
  114. *
  115. *******************************************************************************/
  116. unsigned int _controlfp(unsigned int newctrl, unsigned int mask)
  117. {
  118. return _control87(newctrl, mask & ~_EM_DENORMAL);
  119. }
  120. /***
  121. * _fpreset() - reset fp system
  122. *
  123. *Purpose:
  124. * reset fp environment to the default state
  125. * Also reset saved fp environment if invoked from a user's
  126. * signal handler
  127. *
  128. *Entry:
  129. *
  130. *Exit:
  131. *
  132. *Exceptions:
  133. *
  134. *******************************************************************************/
  135. #define TAG_ALL_EMPTY ((unsigned int) 0xffff);
  136. void _fpreset()
  137. {
  138. #ifndef _POSIX_
  139. PEXCEPTION_POINTERS excptrs = (PEXCEPTION_POINTERS) _pxcptinfoptrs;
  140. #endif
  141. _asm {
  142. fninit
  143. }
  144. _setdefaultprecision(); // reset precision, usually down to 53 bits
  145. #ifndef _POSIX_
  146. if (excptrs &&
  147. excptrs->ContextRecord->ContextFlags & CONTEXT_FLOATING_POINT) {
  148. // _fpreset has been invoked by a signal handler which in turn
  149. // has been invoked by the CRT filter routine. In this case
  150. // the saved fp context should be cleared, so that the change take
  151. // effect on continuation.
  152. FLOATING_SAVE_AREA *pFloatSave = &excptrs->ContextRecord->FloatSave;
  153. pFloatSave->StatusWord = 0;
  154. pFloatSave->TagWord = TAG_ALL_EMPTY;
  155. }
  156. #endif
  157. }
  158. /***
  159. * _abstract_cw() - abstract control word
  160. *
  161. *Purpose:
  162. * produce a fp control word in abstracted (machine independent) form
  163. *
  164. *Entry:
  165. * cw: machine control word
  166. *
  167. *Exit:
  168. *
  169. *Exceptions:
  170. *
  171. *******************************************************************************/
  172. unsigned int _abstract_cw(unsigned short cw)
  173. {
  174. unsigned int abstr = 0;
  175. //
  176. // Set exception mask bits
  177. //
  178. if (cw & IEM_INVALID)
  179. abstr |= _EM_INVALID;
  180. if (cw & IEM_ZERODIVIDE)
  181. abstr |= _EM_ZERODIVIDE;
  182. if (cw & IEM_OVERFLOW)
  183. abstr |= _EM_OVERFLOW;
  184. if (cw & IEM_UNDERFLOW)
  185. abstr |= _EM_UNDERFLOW;
  186. if (cw & IEM_INEXACT)
  187. abstr |= _EM_INEXACT;
  188. if (cw & IEM_DENORMAL)
  189. abstr |= _EM_DENORMAL;
  190. //
  191. // Set rounding mode
  192. //
  193. switch (cw & IMCW_RC) {
  194. case IRC_NEAR:
  195. abstr |= _RC_NEAR;
  196. break;
  197. case IRC_UP:
  198. abstr |= _RC_UP;
  199. break;
  200. case IRC_DOWN:
  201. abstr |= _RC_DOWN;
  202. break;
  203. case IRC_CHOP:
  204. abstr |= _RC_CHOP;
  205. break;
  206. }
  207. //
  208. // Set Precision mode
  209. //
  210. switch (cw & IMCW_PC) {
  211. case IPC_64:
  212. abstr |= _PC_64;
  213. break;
  214. case IPC_53:
  215. abstr |= _PC_53;
  216. break;
  217. case IPC_24:
  218. abstr |= _PC_24;
  219. break;
  220. }
  221. //
  222. // Infinity control (bit can be programmed but has no effect)
  223. //
  224. if (cw & IMCW_IC) {
  225. abstr |= _IC_AFFINE;
  226. }
  227. return abstr;
  228. }
  229. /***
  230. * _hw_cw() - h/w control word
  231. *
  232. *Purpose:
  233. * produce a machine dependent fp control word
  234. *
  235. *
  236. *Entry:
  237. * abstr: abstract control word
  238. *
  239. *Exit:
  240. *
  241. *Exceptions:
  242. *
  243. *******************************************************************************/
  244. unsigned short _hw_cw(unsigned int abstr)
  245. {
  246. //
  247. // Set standard infinity and denormal control bits
  248. //
  249. unsigned short cw = 0;
  250. //
  251. // Set exception mask bits
  252. //
  253. if (abstr & _EM_INVALID)
  254. cw |= IEM_INVALID;
  255. if (abstr & _EM_ZERODIVIDE)
  256. cw |= IEM_ZERODIVIDE;
  257. if (abstr & _EM_OVERFLOW)
  258. cw |= IEM_OVERFLOW;
  259. if (abstr & _EM_UNDERFLOW)
  260. cw |= IEM_UNDERFLOW;
  261. if (abstr & _EM_INEXACT)
  262. cw |= IEM_INEXACT;
  263. if (abstr & _EM_DENORMAL)
  264. cw |= IEM_DENORMAL;
  265. //
  266. // Set rounding mode
  267. //
  268. switch (abstr & _MCW_RC) {
  269. case _RC_NEAR:
  270. cw |= IRC_NEAR;
  271. break;
  272. case _RC_UP:
  273. cw |= IRC_UP;
  274. break;
  275. case _RC_DOWN:
  276. cw |= IRC_DOWN;
  277. break;
  278. case _RC_CHOP:
  279. cw |= IRC_CHOP;
  280. break;
  281. }
  282. //
  283. // Set Precision mode
  284. //
  285. switch (abstr & _MCW_PC) {
  286. case _PC_64:
  287. cw |= IPC_64;
  288. break;
  289. case _PC_53:
  290. cw |= IPC_53;
  291. break;
  292. case _PC_24:
  293. cw |= IPC_24;
  294. break;
  295. }
  296. //
  297. // Set Infinity mode
  298. //
  299. if (abstr & _MCW_IC) {
  300. cw |= IIC_AFFINE;
  301. }
  302. return cw;
  303. }
  304. /***
  305. * _abstract_sw() - abstract fp status word
  306. *
  307. *Purpose:
  308. * produce an abstract (machine independent) fp status word
  309. *
  310. *
  311. *Entry:
  312. * sw: machine status word
  313. *
  314. *Exit:
  315. *
  316. *Exceptions:
  317. *
  318. *******************************************************************************/
  319. unsigned int _abstract_sw(unsigned short sw)
  320. {
  321. unsigned int abstr = 0;
  322. if (sw & ISW_INVALID)
  323. abstr |= _SW_INVALID;
  324. if (sw & ISW_ZERODIVIDE)
  325. abstr |= _SW_ZERODIVIDE;
  326. if (sw & ISW_OVERFLOW)
  327. abstr |= _SW_OVERFLOW;
  328. if (sw & ISW_UNDERFLOW)
  329. abstr |= _SW_UNDERFLOW;
  330. if (sw & ISW_INEXACT)
  331. abstr |= _SW_INEXACT;
  332. if (sw & ISW_DENORMAL)
  333. abstr |= _SW_DENORMAL;
  334. return abstr;
  335. }