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
8.2 KiB

  1. subttl emarith.asm - Arithmetic Operations
  2. page
  3. ;*******************************************************************************
  4. ;emarith.asm - Arithmetic Operations
  5. ;
  6. ; Microsoft Confidential
  7. ;
  8. ; Copyright (c) Microsoft Corporation 1991
  9. ; All Rights Reserved
  10. ;
  11. ;Purpose:
  12. ; Arithmetic Operations
  13. ;
  14. ;Revision History:
  15. ;
  16. ; [] 09/05/91 TP Initial 32-bit version.
  17. ;
  18. ;*******************************************************************************
  19. NextStackWrap esi,TwoOp ;Tied to NextStackElem below
  20. EM_ENTRY eFPREM
  21. eFPREM:
  22. and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3
  23. push offset PremCont ;Return address if normal
  24. PremPointTopTwo:
  25. push offset PremSpclDone ;Return address if special
  26. mov ebp,offset tFpremDisp
  27. PointTopTwo:
  28. mov esi,edi
  29. NextStackElem esi,TwoOp
  30. TwoOpSiDi:
  31. mov ecx,EMSEG:[esi].ExpSgn
  32. mov ebx,EMSEG:[esi].lManHi
  33. mov esi,EMSEG:[esi].lManLo
  34. TwoOpSetResult:
  35. mov EMSEG:[Result],edi ;Save result pointer
  36. TwoOpResultSet:
  37. mov ah,EMSEG:[edi].bTag
  38. TwoOpDispAh:
  39. mov al,cl
  40. TwoOpDispatch:
  41. and eax,TAG_MASK + 100H*TAG_MASK ;Look at internal tags only
  42. shl al,TAG_SHIFT
  43. or al,ah
  44. xor ah,ah ;Zero ah
  45. ;UNDONE: masm bug! ebp + scaled index requires a displacement.
  46. ;UNDONE: No displacement is needed here, so masm should generate a
  47. ;UNDONE: zero. It doesn't! dec eax so we can add 4*1 back.
  48. dec eax ;UNDONE
  49. jmp dword ptr cs:[ebp+4*eax+4];UNDONE Go to appropriate routine.
  50. EM_ENTRY eFPREM1
  51. eFPREM1:
  52. and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3
  53. push offset Prem1Cont ;Return address if normal
  54. jmp PremPointTopTwo
  55. EM_ENTRY eFSCALE
  56. eFSCALE:
  57. mov ebp,offset tFscaleDisp
  58. jmp PointTopTwo
  59. EM_ENTRY eFPATAN
  60. eFPATAN:
  61. mov ebp,offset tFpatanDisp
  62. TopTwoPop:
  63. push offset PopWhenDone
  64. mov esi,edi
  65. add edi,Reg87Len ;edi = ST(1)
  66. cmp edi,ENDstk
  67. jb TwoOpSiDi
  68. mov edi,BEGstk
  69. jmp TwoOpSiDi
  70. EM_ENTRY eFYL2X
  71. eFYL2X:
  72. mov ebp,offset tFyl2xDisp
  73. jmp TopTwoPop
  74. EM_ENTRY eFYL2XP1
  75. eFYL2XP1:
  76. mov ebp,offset tFyl2xp1Disp
  77. jmp TopTwoPop
  78. ;*******************************************************************************
  79. page
  80. ;-----------------------------------------------------------;
  81. ; ;
  82. ; Special Case Routines for Arithmetic Functions ;
  83. ; ;
  84. ;-----------------------------------------------------------;
  85. ;There are four kinds of "specials", encoded in the tag:
  86. ;
  87. ; Empty
  88. ; Infinity
  89. ; NAN (which can be QNAN or SNAN)
  90. ; Denormal
  91. ;
  92. ;Empty always results in an Invalid Operation exception with Stack Flag set
  93. ;and C1 (O/U#) bit clear, and returns Indefinite (a specific QNAN).
  94. ;
  95. ;Operations on NAN return the same NAN except it is always modified to a
  96. ;QNAN. If both operands are NAN, the one with the larger mantissa is
  97. ;returned. An SNAN causes an Invalid Operation exception except for
  98. ;internal FP stack operations, FCHS, and FABS. A QNAN does not cause
  99. ;and exception.
  100. ;
  101. ;Operations on Infinity return a result depending on the operation.
  102. ;
  103. ;UNDONE: Old code plays with sign of NAN when two NANs with equal
  104. ;mantissas are used. Why?
  105. ;"***" means entry point from dispatch tables
  106. ;***
  107. DivSpclSource:
  108. cmp cl,bTAG_INF
  109. jnz SpclSource
  110. ;Division by infinity always returns zero
  111. xor ch,EMSEG:[edi].bSgn
  112. jmp SignedZero ;in emfmul.asm
  113. ;***
  114. MulSpclSource:
  115. cmp cl,bTAG_INF
  116. jnz SpclSource
  117. MulByInf:
  118. cmp EMSEG:[edi].bTag,bTAG_ZERO ;Infinity * zero?
  119. jz ReturnIndefinite
  120. XorSourceSign:
  121. xor ch,EMSEG:[edi].bSgn
  122. jmp SaveResultEdi
  123. ;***
  124. AddSpclSource:
  125. cmp cl,bTAG_INF
  126. jnz SpclSource
  127. xor ch,dl ;Flip sign of infinity if subtracting
  128. jmp SaveResultEdi
  129. DenormalSource:
  130. mov cl,bTAG_VALID ;Change denormal to DOUBLE
  131. mov EMSEG:[CURerr],Denormal
  132. test EMSEG:[CWmask],Denormal ;Is denormal exception masked?
  133. jnz TwoOpResultSet
  134. AbortOp:
  135. mov cl,bTAG_NOPOP ;Unmasked, don't pop stack
  136. ret
  137. DenormalDisp:
  138. ;Repeat dispatch, but for normal ops
  139. jmp dword ptr cs:[ebp+4*(TAG_VALID + TAG_VALID shl TAG_SHIFT)]
  140. ;***
  141. DivrSpclSource:
  142. cmp cl,bTAG_INF
  143. jz XorSourceSign ;Return infinity
  144. SpclSource:
  145. cmp cl,bTAG_DEN
  146. jz DenormalSource
  147. cmp cl,bTAG_EMPTY
  148. jz StackError
  149. ;Must be a NAN
  150. SourceNAN:
  151. test ebx,1 shl 30 ;Check for SNAN
  152. jnz SaveResultEdi ;If QNAN, just use it as result
  153. SourceSNAN:
  154. or EMSEG:[CURerr],Invalid ;Flag the error
  155. or ebx,1 shl 30 ;Make it into a QNAN
  156. test EMSEG:[CWmask],Invalid ;Is it masked?
  157. jnz SaveResultEdi ;If so, update with masked response
  158. mov cl,bTAG_NOPOP ;Unmasked, don't pop stack
  159. ret
  160. ;***
  161. DivrSpclDest:
  162. mov eax,EMSEG:[edi].ExpSgn ;Pick up tag
  163. cmp al,bTAG_INF
  164. jnz SpclDest
  165. ;Division by infinity always returns zero
  166. xor ch,ah
  167. jmp SignedZero ;in emfmul.asm
  168. ;***
  169. MulSpclDest:
  170. mov al,EMSEG:[edi].bTag ;Pick up tag
  171. cmp al,bTAG_INF
  172. jnz SpclDest
  173. cmp cl,bTAG_ZERO ;Infinity * zero?
  174. jz ReturnIndefinite
  175. XorDestSign:
  176. xor EMSEG:[edi].bSgn,ch ;Xor signs
  177. ret
  178. ;***
  179. AddSpclDest:
  180. mov al,EMSEG:[edi].bTag ;Pick up tag
  181. cmp al,bTAG_INF
  182. jnz SpclDest
  183. xor EMSEG:[edi].bSgn,dh ;Flip sign of infinity if subtracting
  184. ret
  185. DenormalDest:
  186. mov ah,bTAG_VALID ;Change denormal to DOUBLE
  187. mov EMSEG:[CURerr],Denormal
  188. test EMSEG:[CWmask],Denormal ;Is denormal exception masked?
  189. jnz TwoOpDispAh
  190. mov cl,bTAG_NOPOP ;Unmasked, don't pop stack
  191. ret
  192. ;***
  193. DivSpclDest:
  194. mov al,EMSEG:[edi].bTag ;Pick up tag
  195. cmp al,bTAG_INF
  196. jz XorDestSign ;Return infinity
  197. SpclDest:
  198. cmp al,bTAG_DEN
  199. jz DenormalDest
  200. SpclDestNotDen:
  201. cmp al,bTAG_EMPTY
  202. jz StackError
  203. ;Must be a NAN
  204. DestNAN:
  205. test EMSEG:[edi].bMan7,40H ;Check for SNAN
  206. jnz ReturnDest ;If QNAN, just use it as result
  207. DestSNAN:
  208. or EMSEG:[CURerr],Invalid ;Flag the error
  209. test EMSEG:[CWmask],Invalid ;Is it masked?
  210. jz AbortOp ;No - preserve value
  211. or EMSEG:[edi].bMan7,40H ;Make it into a QNAN
  212. ret
  213. StackError:
  214. mov EMSEG:[CURerr],Invalid+StackFlag
  215. ReturnIndefinite:
  216. or EMSEG:[CURerr],Invalid
  217. test EMSEG:[CWmask],Invalid ;Is it masked?
  218. jz AbortOp ;No - preserve value
  219. mov EMSEG:[edi].lManLo,0
  220. mov EMSEG:[edi].lManHi,0C0000000H
  221. mov EMSEG:[edi].ExpSgn,TexpMax shl 16 + bSign shl 8 + bTAG_NAN
  222. ReturnDest:
  223. ret
  224. AddTwoInf:
  225. ;Adding two infinites.
  226. ;If signs are the same, return that infinity. Otherwise, Invalid Operation.
  227. xor ch,dl ;Possibly subtracting source
  228. xor ah,dh ;Possibly subtracting dest
  229. xor ch,ah ;Compare signs
  230. js ReturnIndefinite
  231. mov EMSEG:[edi].bSgn,ah ;Correct the sign if subtracting
  232. ret
  233. ;***
  234. TwoOpBothSpcl:
  235. ;ebp = dispatch table address
  236. mov al,EMSEG:[edi].bTag
  237. mov ah,cl
  238. cmp ax,(bTAG_NAN shl 8) + bTag_NAN ;Are both NAN?
  239. jz TwoNANs
  240. cmp cl,bTAG_EMPTY
  241. jz StackError
  242. cmp al,bTAG_EMPTY
  243. jz StackError
  244. cmp cl,bTAG_NAN
  245. jz SourceNAN
  246. cmp al,bTAG_NAN
  247. jz DestNAN
  248. cmp ax,(bTAG_INF shl 8) + bTag_INF ;Are both infinity?
  249. jz TwoInfs
  250. ;At least one of the operands is a denormal
  251. mov EMSEG:[CURerr],Denormal
  252. test EMSEG:[CWmask],Denormal ;Is denormal exception masked?
  253. jz AbortOp ;If not, don't do operation
  254. ;Denormal exception is masked, treat denormals as VALID
  255. ;Dispatch through operation table in ebp again
  256. cmp ax,(bTAG_DEN shl 8) + bTag_DEN ;Are both denormal?
  257. jz DenormalDisp
  258. ;Have an infinity and a denormal
  259. cmp al,bTAG_INF
  260. jz DestInf
  261. ;Source is denormal, Dest is infinity
  262. jmp dword ptr [ebp+4*(TAG_SPCL + TAG_VALID shl TAG_SHIFT)]
  263. DestInf:
  264. ;Source is infinity, Dest is denormal
  265. jmp dword ptr [ebp+4*(TAG_VALID + TAG_SPCL shl TAG_SHIFT)]
  266. TwoNANs:
  267. ;Two NANs. Use largest mantissa
  268. cmp ebx,EMSEG:[edi].lManHi
  269. ja BiggerNAN
  270. jb DestBigger
  271. ;Now we know they're both the same type, SNAN or QNAN
  272. cmp esi,EMSEG:[edi].lManLo
  273. ja SourceNAN
  274. ;UNDONE: Old code did funny business with signs when mantissas were equal
  275. jmp DestNAN
  276. BiggerNAN:
  277. test EMSEG:[edi].bMan7,40H ;Is smaller one SNAN?
  278. jz SourceSNAN
  279. jmp SourceNAN
  280. DestBigger:
  281. test ebx,40H ;Is smaller one SNAN?
  282. jz DestSNAN
  283. jmp DestNAN
  284. TwoInfs:
  285. mov ah,EMSEG:[edi].bSgn
  286. jmp dword ptr [ebp+4*16] ;Go do code for two infinites
  287. ;***
  288. DivideByMinusZero:
  289. mov ch,bSign
  290. ;***
  291. DivideByZero:
  292. or EMSEG:[CURerr],ZeroDivide
  293. test EMSEG:[CWmask],ZeroDivide ;Is exception masked?
  294. jz AbortOp ;No - preserve value
  295. ;Set up a signed infinity
  296. xor ch,EMSEG:[edi].bSgn ;Get result sign
  297. and ecx,1 shl 15 ;Keep only sign bit
  298. or ecx,(4000H+TexpBias) shl 16 + bTAG_INF ;ExpSgn of infinity
  299. mov ebx,1 shl 31
  300. xor esi,esi
  301. jmp SaveResultEdi