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.

309 lines
6.1 KiB

  1. page ,132
  2. title ldsplit - split long double
  3. ;***
  4. ;ldsplit.asm - split long double into two doubles
  5. ;
  6. ; Copyright (c) 1992-2001, Microsoft Corporation. All rights reserved.
  7. ;
  8. ;Purpose:
  9. ; Helper for handling 10byte long double quantities if there is no
  10. ; compiler support.
  11. ;
  12. ;Revision History:
  13. ;
  14. ; 04/21/92 GDP written
  15. ;
  16. ;*******************************************************************************
  17. .xlist
  18. include cruntime.inc
  19. include mrt386.inc
  20. include elem87.inc
  21. include os2supp.inc
  22. .list
  23. .data
  24. labelB TagTable
  25. ; C2 C1 C0 C3 Meaning
  26. db 2 * 4 ; 0 0 0 0 +Unnormal=> NAN
  27. db 1 * 4 ; 0 0 0 1 +Zero => Zero
  28. db 2 * 4 ; 0 0 1 0 +NAN => NAN
  29. db 2 * 4 ; 0 0 1 1 Empty => NAN
  30. db 2 * 4 ; 0 1 0 0 -Unnormal=> NAN
  31. db 1 * 4 ; 0 1 0 1 -Zero => Zero
  32. db 2 * 4 ; 0 1 1 0 -NAN => NAN
  33. db 2 * 4 ; 0 1 1 1 Empty => NAN
  34. db 0 * 4 ; 1 0 0 0 +Normal => Valid
  35. db 4 * 4 ; 1 0 0 1 +Denormal=> Denormal
  36. db 3 * 4 ; 1 0 1 0 +Infinity=> Infinity
  37. db 2 * 4 ; 1 0 1 1 Empty => NAN
  38. db 0 * 4 ; 1 1 0 0 -Normal => Valid
  39. db 4 * 4 ; 1 1 0 1 -Denormal=> Zero
  40. db 3 * 4 ; 1 1 1 0 -Infinity=> Infinity
  41. db 2 * 4 ; 1 1 1 1 Empty => NAN
  42. ; factor = 2^64
  43. staticQ factor, 043F0000000000000R
  44. LDBIAS equ 3fffh
  45. DBIAS equ 3ffh
  46. MAX_BIASED_DEXP equ 7feh
  47. CODESEG
  48. table:
  49. dd valid
  50. dd zero
  51. dd nan
  52. dd inf
  53. dd denorm
  54. ;***
  55. ;int _ldsplit(pld, pd1, pd2) - split long double
  56. ;
  57. ;Purpose:
  58. ; partition a long double quantity ld into two double quantities
  59. ; d1, d2 and an integer scaling factror s. The mantissa of d1 has
  60. ; the high order word of the mantissa of ld. Respectively, the
  61. ; mantissa of d2 has the low order word of the mantissa of ld.
  62. ; The following relation should be satisfied:
  63. ;
  64. ; ld == ((long double)d1 + (long double)d2) * 2^s
  65. ;
  66. ; s is 0, unless d1 or d2 cannot be expressed as normalized
  67. ; doubles; in that case s != 0, and .5 <= d1 < 1
  68. ;
  69. ;
  70. ;Entry:
  71. ; pld pointer to the long double argument
  72. ; pd1 pointer to d1
  73. ; pd2 pointer to d2
  74. ;
  75. ;Exit:
  76. ; *pd1, *pd2 are updated
  77. ; return value is equal to s
  78. ;
  79. ;
  80. ;Exceptions:
  81. ; This function should raise no IEEE exceptions.
  82. ; special cases:
  83. ; ld is QNAN or SNAN: d1 = QNAN, d2 = 0, s = 0
  84. ; ls is INF: d1 = INF, d2 = 0, s = 0
  85. ;
  86. ;
  87. ;******************************************************************************/
  88. _ldsplit proc uses ebx edx edi, pld:dword, pd1:dword, pd2:dword
  89. local ld:tbyte
  90. local exp_adj:dword
  91. local retvalue:dword
  92. local denorm_adj:dword
  93. mov [retvalue], 0 ; default return value
  94. mov [denorm_adj], 0
  95. mov ebx, [pld]
  96. fld tbyte ptr [ebx]
  97. fxam
  98. fstsw ax
  99. fstp [ld] ; store to local area
  100. shl ah, 1
  101. sar ah, 1
  102. rol ah, 1
  103. and ah, 0fh
  104. mov al, ah
  105. mov ebx, dataoffset TagTable ; Prepare for XLAT
  106. xlat
  107. movzx eax, al
  108. mov ebx, OFFSET table
  109. add ebx, eax
  110. mov edx, pd1 ; edx points to the high order double
  111. mov edi, pd2 ; edi points to the low order double
  112. jmp [ebx]
  113. lab valid
  114. ; have a valid normalized non-special long double
  115. mov eax, dword ptr [ld]
  116. or eax, eax
  117. jz d2zero
  118. ; compute mantissa an exponent for d2
  119. mov [exp_adj], 31 ; adjustment to be subtracted from exp of *pd2
  120. ;
  121. ; compute mantissa of d2
  122. ; shift left low order word of ld, until a '1' is hit
  123. ;
  124. cmp eax, 0ffffh
  125. ja shl16done
  126. sal eax, 16
  127. add [exp_adj], 16
  128. lab shl16done
  129. cmp eax, 0ffffffh
  130. ja shl8done
  131. sal eax, 8
  132. add [exp_adj], 8
  133. lab shl8done
  134. lab shiftloop
  135. inc [exp_adj]
  136. sal eax, 1
  137. jnc shiftloop
  138. ; now eax contains the mantissa for d2
  139. ; exp_adj is the difference of the
  140. ; exponents of d1 and d2
  141. ; exp_adj should be in the range
  142. ; 32 <= exp_adj <= 63
  143. ; By convention, if exp_adj is 0 then
  144. ; d2 is zero
  145. lab setd2man
  146. mov dword ptr [edi+4], 0
  147. shld dword ptr [edi+4], eax, 20
  148. shl eax, 20
  149. mov [edi], eax
  150. ;
  151. ; set mantissa of d1
  152. ;
  153. lab setd1man
  154. mov eax, dword ptr [ld+4]
  155. sal eax, 1 ; get rid of explicit bit
  156. mov dword ptr [edx+4], 0
  157. shld dword ptr [edx+4], eax, 20
  158. shl eax, 20
  159. mov [edx], eax
  160. ; check if exponent is in range
  161. mov ax, word ptr [ld+8]
  162. and ax, 07fffh ; clear sign bit
  163. movzx eax, ax
  164. sub eax, LDBIAS - DBIAS
  165. cmp eax, MAX_BIASED_DEXP
  166. ja expoutofrange
  167. cmp eax, [exp_adj]
  168. jb expoutofrange
  169. ;
  170. ; set exponent of d1
  171. ;
  172. lab setexp1
  173. mov ebx, eax ; save exp value
  174. shl eax, 20
  175. or dword ptr [edx+4], eax
  176. cmp [exp_adj], 0
  177. je exp2zero
  178. sub ebx, [exp_adj]
  179. je exp2zero
  180. lab setexp2
  181. shl ebx, 20
  182. or dword ptr [edi+4], ebx
  183. mov [retvalue], 0
  184. lab setsign ; set correct signs and return
  185. ; at this point eax contains
  186. ; the return value
  187. mov bx, word ptr [ld+8]
  188. and bx, 1 SHL 15 ; get sign
  189. or [edi+6], bx ; set sign bit
  190. or [edx+6], bx ; set sign bit
  191. mov eax, [retvalue]
  192. add eax, [denorm_adj]
  193. ret
  194. lab d2zero
  195. mov [exp_adj], 0
  196. jmp setd2man
  197. lab exp2zero
  198. mov ebx, 0
  199. jmp setexp2
  200. lab expoutofrange
  201. mov ebx, DBIAS
  202. mov ecx, ebx
  203. sub ecx, [exp_adj]
  204. shl ebx, 20
  205. or dword ptr [edx+4], ebx
  206. shl ecx, 20
  207. or dword ptr [edi+4], ecx
  208. sub eax, DBIAS ; unbias exp
  209. mov [retvalue], eax ; this is the return value
  210. jmp short setsign
  211. lab zero
  212. mov dword ptr [edx], 0
  213. mov dword ptr [edx+4], 0
  214. mov dword ptr [edi], 0
  215. mov dword ptr [edi+4], 0
  216. jmp setsign
  217. lab nan
  218. mov dword ptr [edx], 0
  219. mov dword ptr [edx+4], 07ff80000h
  220. mov dword ptr [edi], 0
  221. mov dword ptr [edi+4], 0
  222. jmp setsign
  223. lab inf
  224. mov dword ptr [edx], 0
  225. mov dword ptr [edx+4], 07ff00000h
  226. mov dword ptr [edi], 0
  227. mov dword ptr [edi+4], 0
  228. jmp setsign
  229. lab denorm
  230. ;
  231. ; We have a long double denormal
  232. ; so we know for sure that this is out of the double
  233. ; precision range, and the return value of _ldsplit
  234. ; should be non-zero.
  235. ; Multiply the denormal by 2^64, then adjust the
  236. ; return value by subtracting 64
  237. ;
  238. ; this assumes denormal exception masked
  239. fld [ld]
  240. fmul [factor]
  241. fstp [ld]
  242. mov [denorm_adj], 64
  243. jmp valid
  244. _ldsplit endp
  245. end