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.

335 lines
11 KiB

  1. ;***
  2. ;
  3. ; Copyright (c) 1984-2001, Microsoft Corporation. All rights reserved.
  4. ;
  5. ;Revision History:
  6. ;
  7. ;*******************************************************************************
  8. .xlist
  9. include cruntime.inc
  10. include elem87.inc
  11. .list
  12. .const
  13. staticQ One, 03FF0000000000000R
  14. globalW _DEFAULT_CW_in_mem 027fh
  15. globalT _pi_by_2_to_61 0403ec90fdaa22168c235R ; (2**61) * pi
  16. staticQ DblMax, 07fefffffffffffffR
  17. staticQ DblMin, 00010000000000000R
  18. staticQ IeeeAdjO, 0c098000000000000R
  19. staticQ IeeeAdjU, 04098000000000000R
  20. staticQ _infinity, 07ff0000000000000R
  21. staticQ _zero, 00000000000000000R
  22. CODESEG
  23. extrn _startOneArgErrorHandling:near
  24. extrn _startTwoArgErrorHandling:near
  25. ;***********************************************************
  26. ;
  27. ; _twoToTOS
  28. ;
  29. ;***********************************************************
  30. ; Recieves:
  31. ; TOS is not NaN
  32. ; Retunns:
  33. ; 2^TOS
  34. ; Note:
  35. ; uses 3 entries of FPU stack
  36. _twoToTOS proc
  37. fld st(0) ; duplicate stack top
  38. frndint ; N = round(y)
  39. fsubr st(1), st
  40. fxch
  41. fchs ; g = y - N where abs(g) < 1
  42. f2xm1 ; 2**g - 1
  43. fld1
  44. fadd ; 2**g
  45. fscale ; (2**g) * (2**N) - gives 2**y
  46. fstp st(1)
  47. ret ; pop extra stuff from fp stack
  48. _twoToTOS endp
  49. ;***********************************************************
  50. ;
  51. ; _load_CW
  52. ;
  53. ;***********************************************************
  54. ; receives current control word on stack
  55. ; and it's known that it differs from default
  56. ; Purpose:
  57. ; load default CW, but take precision from current CW (bits 8 and 9)
  58. ; Note:
  59. ; value of edx is destroyed
  60. ;
  61. _load_CW proc
  62. mov edx,[esp+4]
  63. and edx,0300H ; all bits except precision are zero
  64. or edx,DEFAULT_CW_without_precision
  65. mov [esp+6],dx ; use 2 free bytes in stack
  66. fldcw [esp+6]
  67. ret
  68. _load_CW endp
  69. ;***********************************************************
  70. ;
  71. ; _convertTOStoQNaN
  72. ;
  73. ;***********************************************************
  74. ; Recieves:
  75. ; TOS is QNaN or SNaN
  76. ; eax is high dword of TOS
  77. ; Retunns:
  78. ; if TOS=QNaN
  79. ; eax=DOMAIN_QNAN
  80. ; else (TOS=SNaN)
  81. ; eax=DOMAIN
  82. ; TOS=QNaN
  83. _convertTOStoQNaN proc
  84. test eax, 00080000H ; test weather arg is QNaN or SNaN
  85. jz tosIsSNaN
  86. mov eax,DOMAIN_QNAN ; TOS is QNaN
  87. ret
  88. tosIsSNaN:
  89. fadd [One] ; convert SNaN to QNan
  90. mov eax,DOMAIN ; TOS was SNaN
  91. ret ; _cdecl return
  92. _convertTOStoQNaN endp
  93. ;***********************************************************
  94. ;
  95. ; _fload_withFB
  96. ;
  97. ;***********************************************************
  98. ; Load arg in the fp stack without raising an exception if the argument
  99. ; is a signaling NaN
  100. ; In other words, when arg is 53-bit SNaN convert it to 64-bit SNaN
  101. ;
  102. ; edx points to argument (in double precision)
  103. ; return value:
  104. ; if we have normal number:
  105. ; eax=exponent
  106. ; Zero flag is 0
  107. ; if we have special number:
  108. ; eax=high dword
  109. ; Zero flag is 1
  110. _fload_withFB proc ; load with feed back
  111. mov eax, [edx+4] ; get exponent field
  112. and eax, 07ff00000h
  113. cmp eax, 07ff00000h ; check for special exponent
  114. je fpload_special
  115. fld qword ptr[edx] ; ZF=0
  116. ret ; _cdecl return
  117. ; have special argument (NaN or INF)
  118. fpload_special: ; convert to long double
  119. mov eax,[edx+4] ; high dword of double
  120. sub esp,LDBLSIZE
  121. or eax, 7fff0000h ; preserve sign, set max long double exp
  122. mov [esp+6],eax ; store sign and power
  123. mov eax,[edx+4] ; low dword of double
  124. mov ecx,[edx]
  125. shld eax,ecx,11
  126. shl ecx,11
  127. mov [esp+4],eax
  128. mov [esp],ecx
  129. fld tbyte ptr [esp]
  130. add esp,LDBLSIZE
  131. test eax,0 ; ZF=1
  132. mov eax,[edx+4] ; high dword of double
  133. ret ; _cdecl return
  134. _fload_withFB endp
  135. ;***********************************************************
  136. ;
  137. ; _checkTOS_withFB
  138. ;
  139. ;***********************************************************
  140. ; Test first argument on INTEGER stack and set registers and flags exactly like _fload_withFB
  141. ;
  142. ; we have on stack : ret_value(4 bytes), arg1(8 bytes)
  143. ; return value:
  144. ; if we have normal number:
  145. ; eax=exponent
  146. ; Zero flag is 0
  147. ; if we have special number:
  148. ; eax=high dword
  149. ; Zero flag is 1
  150. _checkTOS_withFB proc
  151. mov eax, [esp+8] ; get high dword
  152. and eax,07ff00000h
  153. cmp eax,07ff00000h ; check for special exponent
  154. ; and set ZF
  155. je special_exp
  156. ret ; _cdecl return
  157. special_exp:
  158. mov eax, [esp+8] ; get exponent field
  159. ret ; _cdecl return
  160. _checkTOS_withFB endp
  161. ;***********************************************************
  162. ;
  163. ; _fast_exit
  164. ;
  165. ;***********************************************************
  166. ; called after execution of each math function (sin,cos, ....),
  167. ; and if __fastflag!=0
  168. ;
  169. _fast_exit proc
  170. cmp word ptr[esp],default_CW
  171. je fast_exit_CW_is_restored
  172. fldcw [esp]
  173. fast_exit_CW_is_restored:
  174. pop edx ; remove saved CW from stack
  175. ret ; _cdecl return
  176. _fast_exit endp
  177. ;***********************************************************
  178. ;
  179. ; _math_exit
  180. ;
  181. ;***********************************************************
  182. ; called after execution of each math function (sin,cos, ....)
  183. ; and if __fastflag=0.
  184. ; The purpose is to check inexact exception.
  185. ; ecx points to function name
  186. ; edx function id (for example OP_LOG)
  187. _math_exit proc
  188. mov ax,word ptr[esp]
  189. cmp ax,default_CW
  190. je CW_is_restored ; we assume here that in default CW inexact
  191. ; exception is masked
  192. and ax,20h ; test if inexact exception is masked
  193. jz restore_CW
  194. fstsw ax
  195. and ax,20h
  196. jz restore_CW
  197. mov eax,INEXACT
  198. call _startOneArgErrorHandling
  199. pop edx ; remove saved CW from stack
  200. ret
  201. restore_CW:
  202. fldcw [esp]
  203. CW_is_restored:
  204. pop edx ; remove saved CW from stack
  205. ret ; _cdecl return
  206. _math_exit endp
  207. ;***********************************************************
  208. ;
  209. ; _check_overflow_exit
  210. ;
  211. ;***********************************************************
  212. ;
  213. _check_overflow_exit proc
  214. sub esp,DBLSIZE ; prepare place for argument
  215. fst qword ptr[esp]
  216. mov eax,[esp+4] ; eax=high dword
  217. add esp,DBLSIZE
  218. and eax,7ff00000H
  219. jmp _check_overflow_start
  220. _check_overflow_exit endp
  221. ;***********************************************************
  222. ;
  223. ; _check_range_exit
  224. ;
  225. ;***********************************************************
  226. ; called after execution of math functions, which may generate
  227. ; overflow/underflow, and if __fastflag=0.
  228. ; used in exp() and pow() functions
  229. ; The purpose is to check inexact overflow/underflow and inexact exception
  230. ; ecx points to function name
  231. ; edx function id (for example OP_EXP)
  232. _check_range_exit proc
  233. sub esp,DBLSIZE ; prepare place for argument
  234. fst qword ptr[esp]
  235. mov eax,[esp+4] ; eax=high dword
  236. add esp,DBLSIZE
  237. and eax,7ff00000H
  238. jz haveunderflow
  239. _check_overflow_start label proc
  240. cmp eax,7ff00000H
  241. jz haveoverflow
  242. ; check INEXACT(precision) exception
  243. mov ax,word ptr[esp] ; saved CW
  244. cmp ax,default_CW
  245. je CW_is_restored ; we assume here that in default CW inexact
  246. ; exception is masked
  247. and ax,20h ; test if inexact exception is masked
  248. jnz restore_CW
  249. fstsw ax
  250. and ax,20h
  251. jz restore_CW
  252. mov eax,INEXACT
  253. have_error:
  254. cmp edx,OP_POW
  255. je have_error_in_pow
  256. call _startOneArgErrorHandling
  257. pop edx ; remove saved CW from stack
  258. ret
  259. have_error_in_pow:
  260. call _startTwoArgErrorHandling
  261. pop edx ; remove saved CW from stack
  262. ret
  263. restore_CW:
  264. fldcw [esp]
  265. CW_is_restored:
  266. pop edx ; remove saved CW from stack
  267. ret ; _cdecl return
  268. ; this code is taken from previous version, to receive
  269. ; exactly the same result as before. But we may simplify it...
  270. haveunderflow: ; underflow is detected
  271. fld IeeeAdjU
  272. fxch
  273. fscale
  274. fstp st(1)
  275. fld st(0)
  276. fabs
  277. fcomp [DblMin]
  278. fstsw ax
  279. sahf
  280. mov eax,UNDERFLOW
  281. JSAE have_error
  282. fmul [_zero]
  283. jmp short have_error
  284. haveoverflow: ; overflow is detected
  285. fld IeeeAdjO
  286. fxch
  287. fscale
  288. fstp st(1)
  289. fld st(0)
  290. fabs
  291. fcomp [DblMax]
  292. fstsw ax
  293. sahf
  294. mov eax,OVERFLOW
  295. JSBE have_error
  296. fmul [_infinity]
  297. jmp short have_error
  298. _check_range_exit endp
  299. end