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.

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