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.

803 lines
22 KiB

  1. subttl emstore.asm - FST, FSTP, FIST, FISTP instructions
  2. page
  3. ;*******************************************************************************
  4. ;emstore.asm - FST, FSTP, FIST, FISTP instructions
  5. ;
  6. ; Microsoft Confidential
  7. ;
  8. ; Copyright (c) Microsoft Corporation 1991
  9. ; All Rights Reserved
  10. ;
  11. ;Purpose:
  12. ; FST, FSTP, FIST, FISTP instructions
  13. ;Inputs:
  14. ; edi = [CURstk]
  15. ; dseg:esi = pointer to memory destination
  16. ;
  17. ;Revision History:
  18. ;
  19. ; [] 09/05/91 TP Initial 32-bit version.
  20. ;
  21. ;*******************************************************************************
  22. ;******
  23. EM_ENTRY eFSTP
  24. eFSTP:
  25. ;******
  26. ; edi = [CURstk]
  27. ; esi = pointer to st(i) from instruction field
  28. cmp EMSEG:[edi].bTag,bTAG_EMPTY
  29. jz short efstp_StackError
  30. ;UNDONE: temporary hack to preserve condition codes
  31. mov ax,[esp+4].OldStatus
  32. mov EMSEG:[StatusWord],ax
  33. ;UNDONE: end of hack
  34. ;A common use of this instruction is FSTP st(0) just to pop the stack.
  35. ;We check for this case and optimize it.
  36. cmp esi,edi
  37. jz short JustPop
  38. ;Copy the register
  39. mov eax,EMSEG:[edi].ExpSgn
  40. mov EMSEG:[esi].ExpSgn,eax
  41. mov eax,EMSEG:[edi].lManHi
  42. mov EMSEG:[esi].lManHi,eax
  43. mov eax,EMSEG:[edi].lManLo
  44. mov EMSEG:[esi].lManLo,eax
  45. JustPop:
  46. POPSTret edi
  47. efstp_StackError:
  48. mov EMSEG:[CURerr],Invalid+StackFlag
  49. ret
  50. ;******
  51. EM_ENTRY eFST
  52. eFST:
  53. ;******
  54. ; edi = [CURstk]
  55. ; esi = pointer to st(i) from instruction field
  56. cmp EMSEG:[edi].bTag,bTAG_EMPTY
  57. jz StackError ;In emarith.asm
  58. ;Copy the register
  59. mov eax,EMSEG:[edi].ExpSgn
  60. mov EMSEG:[esi].ExpSgn,eax
  61. mov eax,EMSEG:[edi].lManHi
  62. mov EMSEG:[esi].lManHi,eax
  63. mov eax,EMSEG:[edi].lManLo
  64. mov EMSEG:[esi].lManLo,eax
  65. DontPop:
  66. ret
  67. ;Come here if the instruction wants to pop the stack
  68. PopStackChk:
  69. jc DontPop ;Get unmasked error?
  70. PopStack:
  71. mov edi,EMSEG:[CURstk]
  72. POPSTret edi
  73. StoreSpcl64:
  74. cmp cl,bTAG_DEN
  75. jz Denorm64
  76. .erre bTAG_NAN lt bTAG_EMPTY
  77. .erre bTAG_NAN gt bTAG_INF
  78. cmp cl,bTAG_NAN
  79. mov ecx,DexpMax shl 16 ;Insert special exponent for NAN/Inf.
  80. jb StoreIEEE64 ;Go handle infinity
  81. ja Empty64
  82. ;Have a NAN.
  83. test ebx,1 shl 30 ;Check for SNAN
  84. jnz StoreIEEE64 ;Go store QNAN
  85. or ebx,1 shl 30 ;Make SNAN into a QNAN
  86. mov EMSEG:[CURerr],Invalid ;Flag the exception
  87. test EMSEG:[CWmask],Invalid ;Is it masked?
  88. jnz StoreIEEE64 ;If so, update with masked response
  89. stc ;Don't pop stack
  90. ret
  91. Empty64:
  92. ;It's empty--signal invalid operation
  93. mov EMSEG:[CURerr],StackFlag+Invalid
  94. test EMSEG:[CWmask],Invalid ;Is it masked?
  95. jz DoNothing64 ;No--leave memory unchanged
  96. ;Store Indefinite
  97. ;For FSTP, we go ahead and do the pop even though it's empty
  98. mov dword ptr dseg:[esi],0
  99. mov dword ptr dseg:[esi+4],0FFF80000H ;64-bit IEEE indefinite
  100. ret ;CY clear
  101. Denorm64:
  102. mov EMSEG:[CURerr],Denormal
  103. test EMSEG:[CWmask],Denormal ;Is it masked?
  104. jnz NormStore64 ;If so, ignore denormalization
  105. DoNothing64:
  106. stc ;Don't pop stack
  107. ret
  108. ;*****************
  109. ;Store Double Real
  110. ;*****************
  111. EM_ENTRY eFSTP64
  112. eFSTP64:
  113. push offset PopStackChk ;Return here after store
  114. EM_ENTRY eFST64
  115. eFST64:
  116. mov EMSEG:[PrevDataOff],esi ;Save operand pointer
  117. mov ebx,EMSEG:[edi].lManHi
  118. mov ecx,EMSEG:[edi].ExpSgn
  119. mov edi,EMSEG:[edi].lManLo
  120. ;mantissa in ebx:edi, exponent in high ecx, sign in ch bit 7, tag in cl
  121. ;memory destination is dseg:esi
  122. mov al,ch ;Save sign bit
  123. cmp cl,bTAG_ZERO
  124. .erre bTAG_VALID lt bTAG_ZERO
  125. .erre bTAG_SNGL lt bTAG_ZERO
  126. jz short SignAndStore64 ;Just set sign and exit
  127. ja StoreSpcl64
  128. NormStore64:
  129. ;Note that we could have a denormal exception at this point.
  130. ;Thus any additional exceptions must OR into [CURerr], not MOV.
  131. xor cx,cx
  132. add ecx,(DexpBias-TexpBias) shl 16 ;Correct bias
  133. jl short Under64
  134. cmp ecx,DexpMax shl 16 ;Exponent too big?
  135. jge Over64
  136. test edi,(1 shl 11) - 1 ;Any bits to round?
  137. jz short StoreIEEE64
  138. Round64:
  139. or EMSEG:[CURerr],Precision ;Set flag on inexact result
  140. test EMSEG:[CWcntl],RoundControl ;Check rounding control bits
  141. .erre RCnear eq 0
  142. jnz NotNearest64 ;Not just round-to-nearest
  143. test edi,1 shl 10 ;Check rounding bit
  144. jz short StoreIEEE64 ;If zero, don't round up
  145. test edi,(3 shl 10)-1 ;Test LSB and sticky bits
  146. jnz RoundUp64b
  147. StoreIEEE64:
  148. or ecx, ecx ;now that value is rounded,
  149. je short Under64 ;check exponent for underflow
  150. StoreIEEE64Continue:
  151. and ebx,not (1 shl 31) ;Clear MSB--it's implied in IEEE64
  152. shrd edi,ebx,11
  153. shr ebx,11 ;Move mantissa down
  154. shl ecx,4 ;Exponent up to position
  155. or ebx,ecx ;Combine exponent
  156. SignAndStore64:
  157. and al,bSign ;Just sign bit
  158. shl eax,24 ;Sign to MSB
  159. or ebx,eax ;Combine sign
  160. mov dseg:[esi],edi
  161. mov dseg:[esi+4],ebx
  162. ;CY clear indicate no error
  163. ret
  164. SetUnderflow:
  165. or EMSEG:[CURerr],Underflow ;Unmasked underflow--do nothing
  166. DoNothing:
  167. stc ;Indicate nothing was done
  168. ret
  169. Under64:
  170. dec cl ; Is cx == 1?
  171. jz short StoreIEEE64Continue ; Yes, we've alread been here
  172. test EMSEG:[CWmask],Underflow ;Is underflow masked?
  173. jz SetUnderflow ;No, do nothing more
  174. ;Produce masked underflow response
  175. ;Note that the underflow exception does not occur if the number can be
  176. ;represented exactly as a denormal.
  177. sar ecx,16 ;Bring exponent down
  178. cmp ecx,DexpMin-52 ;Allow for shift down to rounding bit
  179. jl BigUnder64 ;Too small, just make it zero
  180. .erre DexpMin eq 0
  181. neg ecx ;Use as shift count
  182. inc ecx ;Shift by at least one
  183. xor edx,edx ;Place for sticky bits
  184. cmp cl,32 ;Long shift?
  185. jb ShortDenorm
  186. neg edi ;CY set if non-zero
  187. sbb edx,edx ;-1 if bits shifted off, else zero
  188. mov edi,ebx
  189. xor ebx,ebx ;32-bit right shift
  190. ShortDenorm:
  191. ;Shift count is modulo-32
  192. shrd edx,edi,cl
  193. shrd edi,ebx,cl
  194. shr ebx,cl
  195. cmp edx,1 ;CY set if zero, else clear
  196. sbb edx,edx ;Zero if bits shifted off, else -1
  197. inc edx ;1 if bits shifted off, else zero
  198. or edi,edx ;Collapse sticky bits into edi
  199. mov ecx, 1 ;Biased exponent is zero, put 1 into CL (noticed by Under64)
  200. test edi,(1 shl 11) - 1 ;Any bits to round?
  201. jz StoreIEEE64 ;If not, no exception
  202. or EMSEG:[CURerr],Underflow
  203. jmp Round64
  204. Over64:
  205. test EMSEG:[CWmask],Overflow ;Is overflow masked?
  206. jz SetOverflow ;No, do nothing more
  207. ;Produce masked overflow response
  208. or EMSEG:[CURerr],Overflow+Precision
  209. mov ebx,DexpMax shl 20
  210. xor edi,edi ;ebx:edi = positive infinity
  211. mov ah,EMSEG:[CWcntl] ;Get rounding control
  212. ;Return max value if RCup bit = 1 and -, or RCdown bit = 1 and +
  213. ;i.e., RCup & sign OR RCdown & not sign
  214. .erre RCchop eq RCup + RCdown ;Always return max value
  215. .erre RCnear eq 0 ;Never return max value
  216. sar al,7 ;Expand sign through whole byte
  217. .erre (RCdown and bSign) eq 0 ;Don't want to change real sign
  218. xor al,RCdown ;Flip sign for RCdown bit
  219. and ah,al ;RCup & sign OR RCdown & not sign
  220. test ah,RoundControl ;Look only at RC bits
  221. jz SignAndStore64 ;Return infinity
  222. dec ebx
  223. dec edi ;Max value == infinity-1
  224. jmp SignAndStore64
  225. SetOverflow:
  226. or EMSEG:[CURerr],Overflow
  227. stc ;Indicate nothing was done
  228. ret
  229. BigUnder64:
  230. or EMSEG:[CURerr],Underflow+Precision
  231. xor ebx,ebx
  232. mov edi,ebx ;Set it to zero
  233. mov ecx,ebx ;Including exponent
  234. NotNearest64:
  235. ;We want to increase the magnitude if RCup and +, or RCdown and -
  236. mov ah,EMSEG:[CWcntl] ;Get rounding control
  237. sar al,7 ;Expand sign through whole byte
  238. .erre (not RCup and RoundControl) eq RCdown
  239. xor ah,al ;Flip rounding bits if negative
  240. and ah,RoundControl
  241. cmp ah,RCup
  242. jnz StoreIEEE64 ;No, chop it
  243. RoundUp64b:
  244. mov EMSEG:[SWcc],RoundUp
  245. add edi,1 shl 11 ;Round up
  246. adc ebx,0
  247. jnc StoreIEEE64
  248. add ecx,1 shl 16 ;Mantissa overflowed, bump exponent
  249. cmp ecx,DexpMax shl 16 ;Exponent too big?
  250. jge Over64
  251. jmp StoreIEEE64
  252. ;*******************************************************************************
  253. StoreSpcl32:
  254. cmp cl,bTAG_DEN
  255. jz Denorm32
  256. .erre bTAG_NAN lt bTAG_EMPTY
  257. .erre bTAG_NAN gt bTAG_INF
  258. cmp cl,bTAG_NAN
  259. mov ecx,SexpMax shl 16 ;Insert special exponent
  260. jb StoreIEEE32
  261. ja Empty64
  262. ;Have a NAN.
  263. test ebx,1 shl 30 ;Check for SNAN
  264. jnz StoreIEEE32 ;Go store QNAN
  265. or ebx,1 shl 30 ;Make SNAN into a QNAN
  266. mov EMSEG:[CURerr],Invalid ;Flag the exception
  267. test EMSEG:[CWmask],Invalid ;Is it masked?
  268. jnz StoreIEEE32 ;If so, update with masked response
  269. stc ;Don't pop stack
  270. ret
  271. Empty32:
  272. ;It's empty--signal invalid operation
  273. mov EMSEG:[CURerr],StackFlag+Invalid
  274. test EMSEG:[CWmask],Invalid ;Is it masked?
  275. jz DoNothing32 ;No--leave memory unchanged
  276. ;Store Indefinite
  277. ;For FSTP, we go ahead and do the pop even though it's empty
  278. mov dword ptr dseg:[esi],0FFC00000H ;32-bit IEEE indefinite
  279. ret ;CY clear
  280. Denorm32:
  281. mov EMSEG:[CURerr],Denormal
  282. test EMSEG:[CWmask],Denormal ;Is it masked?
  283. jnz NormStore32 ;If so, ignore denormalization
  284. DoNothing32:
  285. stc ;Don't pop stack
  286. ret
  287. ;*****************
  288. ;Store Single Real
  289. ;*****************
  290. EM_ENTRY eFSTP32
  291. eFSTP32:
  292. push offset PopStackChk ;Return here after store
  293. EM_ENTRY eFST32
  294. eFST32:
  295. mov EMSEG:[PrevDataOff],esi ;Save operand pointer
  296. mov ebx,EMSEG:[edi].lManHi
  297. mov ecx,EMSEG:[edi].ExpSgn
  298. mov edi,EMSEG:[edi].lManLo
  299. ;mantissa in ebx:edi, exponent in high ecx, sign in ch bit 7, tag in cl
  300. ;memory destination is dseg:esi
  301. mov al,ch ;Save sign bit
  302. cmp cl,bTAG_ZERO
  303. .erre bTAG_VALID lt bTAG_ZERO
  304. .erre bTAG_SNGL lt bTAG_ZERO
  305. jz SignAndStore32 ;Just set sign and exit
  306. ja StoreSpcl32
  307. NormStore32:
  308. ;Note that we could have a denormal exception at this point.
  309. ;Thus any additional exceptions must OR into [CURerr], not MOV.
  310. xor cx,cx
  311. add ecx,(SexpBias-TexpBias) shl 16 ;Correct bias
  312. jle Under32
  313. cmp ecx,SexpMax shl 16 ;Exponent too big?
  314. jge Over32
  315. ;See if we need to round
  316. mov edx,ebx ;Get low bits
  317. and edx,(1 shl 8) - 1 ;Mask to last 8 bits
  318. or edx,edi ;Throwing away any bits?
  319. jz StoreIEEE32
  320. ;Result will not be exact--check rounding mode
  321. Round32:
  322. or EMSEG:[CURerr],Precision ;Set flag on inexact result
  323. test EMSEG:[CWcntl],RoundControl ;Check rounding control bits
  324. .erre RCnear eq 0
  325. jnz NotNearest32 ;Not just round-to-nearest
  326. test bl,1 shl 7 ;Round bit set?
  327. jz StoreIEEE32
  328. mov edx,ebx
  329. and edx,(3 shl 7)-1 ;Mask to LSB and sticky bits
  330. or edx,edi ;Combine with remaining sticky bits
  331. jz StoreIEEE32
  332. mov EMSEG:[SWcc],RoundUp
  333. add ebx,1 shl 8 ;Round up
  334. jc AddOneExp32
  335. StoreIEEE32:
  336. and ebx,not (1 shl 31) ;Clear MSB--it's implied in IEEE32
  337. shr ebx,8 ;Move mantissa down
  338. shl ecx,7 ;Exponent up to position
  339. or ebx,ecx ;Combine exponent
  340. SignAndStore32:
  341. and al,bSign ;Just sign bit
  342. shl eax,24 ;Sign to MSB
  343. or ebx,eax ;Combine sign
  344. mov dseg:[esi],ebx
  345. ;CY clear indicate no error
  346. ret
  347. Under32:
  348. test EMSEG:[CWmask],Underflow ;Is underflow masked?
  349. jz SetUnderflow ;No, do nothing more
  350. ;Produce masked underflow response
  351. ;Note that the underflow exception does not occur if the number can be
  352. ;represented exactly as a denormal.
  353. sar ecx,16 ;Bring exponent down
  354. cmp ecx,SexpMin-23 ;Allow for shift down to rounding bit
  355. jl BigUnder32 ;Too small, just make it zero
  356. .erre SexpMin eq 0
  357. neg ecx ;Use as shift count
  358. inc ecx ;Shift by at least one
  359. xor edx,edx ;Place for sticky bits
  360. shrd edx,ebx,cl
  361. shr ebx,cl
  362. xor ecx,ecx ;Biased exponent is zero
  363. or edi,edx ;Combine sticky bits
  364. mov edx,ebx ;Get low bits
  365. and edx,(1 shl 8) - 1 ;Mask to last 8 bits
  366. or edx,edi ;Throwing away any bits?
  367. jz StoreIEEE32
  368. or EMSEG:[CURerr],Underflow
  369. jmp Round32
  370. AddOneExp32:
  371. add ecx,1 shl 16 ;Mantissa overflowed, bump exponent
  372. cmp ecx,SexpMax shl 16 ;Exponent too big?
  373. jl StoreIEEE32
  374. Over32:
  375. test EMSEG:[CWmask],Overflow ;Is overflow masked?
  376. jz SetOverflow ;No, do nothing more
  377. ;Produce masked overflow response
  378. or EMSEG:[CURerr],Overflow+Precision
  379. mov ebx,SexpMax shl 23
  380. mov ah,EMSEG:[CWcntl] ;Get rounding control
  381. ;Return max value if RCup bit = 1 and -, or RCdown bit = 1 and +
  382. ;i.e., RCup & sign OR RCdown & not sign
  383. .erre RCchop eq RCup + RCdown ;Always return max value
  384. .erre RCnear eq 0 ;Never return max value
  385. sar al,7 ;Expand sign through whole byte
  386. .erre (RCdown and bSign) eq 0 ;Don't want to change real sign
  387. xor al,RCdown ;Flip sign for RCdown bit
  388. and ah,al ;RCup & sign OR RCdown & not sign
  389. test ah,RoundControl ;Look only at RC bits
  390. jz SignAndStore32 ;Return infinity
  391. dec ebx ;Max value == infinity-1
  392. jmp SignAndStore32
  393. BigUnder32:
  394. or EMSEG:[CURerr],Underflow+Precision
  395. xor ebx,ebx ;Set it to zero
  396. xor ecx,ecx ;Exponent too
  397. NotNearest32:
  398. ;We want to increase the magnitude if RCup and +, or RCdown and -
  399. mov ah,EMSEG:[CWcntl] ;Get rounding control
  400. sar al,7 ;Expand sign through whole byte
  401. .erre (not RCup and RoundControl) eq RCdown
  402. xor ah,al ;Flip rounding bits if negative
  403. and ah,RoundControl
  404. cmp ah,RCup
  405. jnz StoreIEEE32 ;No, chop it
  406. mov EMSEG:[SWcc],RoundUp
  407. add ebx,1 shl 8 ;Round up
  408. jnc StoreIEEE32
  409. jmp AddOneExp32
  410. ;*******************************************************************************
  411. StoreSpcl32Int:
  412. cmp cl,bTAG_DEN
  413. jz NormStore32Int ;Ignore denormal
  414. cmp cl,bTAG_EMPTY
  415. jnz Over32Int ;All other specials are invalid
  416. mov EMSEG:[CURerr],StackFlag+Invalid
  417. jmp Invalid32Int
  418. DoNothing32Int:
  419. stc ;Don't pop stack
  420. ret
  421. CheckMax32:
  422. ja Over32Int
  423. test al,bSign ;Is it negative?
  424. jnz Store32Int ;If so, answer is OK
  425. Over32Int:
  426. ;Overflow on integer store is invalid according to IEEE
  427. mov EMSEG:[CURerr],Invalid ;Must remove precision exception
  428. Invalid32Int:
  429. test EMSEG:[CWmask],Invalid ;Is it masked?
  430. jz DoNothing32Int ;No--leave memory unchanged
  431. ;Store Indefinite
  432. ;For FSTP, we go ahead and do the pop even though it's empty
  433. mov dword ptr dseg:[esi],80000000H ;32-bit integer indefinite
  434. ret ;CY clear
  435. ;******************
  436. ;Store Long Integer
  437. ;******************
  438. EM_ENTRY eFISTP32
  439. eFISTP32:
  440. push offset PopStackChk ;Return here after store
  441. EM_ENTRY eFIST32
  442. eFIST32:
  443. mov EMSEG:[PrevDataOff],esi ;Save operand pointer
  444. mov ebx,EMSEG:[edi].lManHi
  445. mov ecx,EMSEG:[edi].ExpSgn
  446. mov edi,EMSEG:[edi].lManLo
  447. ;mantissa in ebx:edi, exponent in high ecx, sign in ch bit 7, tag in cl
  448. ;memory destination is dseg:esi
  449. mov al,ch ;Save sign bit
  450. cmp cl,bTAG_ZERO
  451. .erre bTAG_VALID lt bTAG_ZERO
  452. .erre bTAG_SNGL lt bTAG_ZERO
  453. jz Store32Int ;Just store zero and exit
  454. ja StoreSpcl32Int
  455. NormStore32Int:
  456. xor edx,edx
  457. sar ecx,16 ;Bring exponent down
  458. cmp ecx,-1 ;Is it less than 1?
  459. jle Under32Int
  460. cmp ecx,31
  461. jg Over32Int
  462. sub ecx,31
  463. neg ecx ;cl = amount to shift right
  464. shrd edx,edi,cl
  465. shrd edi,ebx,cl ;Collect round and sticky bits
  466. shr ebx,cl ;Align integer
  467. ;See if we need to round
  468. mov ecx,edi
  469. or ecx,edx ;Throwing away any bits?
  470. jz StoreIEEE32Int
  471. ;Result will not be exact--check rounding mode
  472. Round32Int:
  473. mov EMSEG:[CURerr],Precision ;Set flag on inexact result
  474. test EMSEG:[CWcntl],RoundControl ;Check rounding control bits
  475. .erre RCnear eq 0
  476. jnz NotNearest32Int ;Not just round-to-nearest
  477. ;To perform "round even" when the round bit is set and the sticky bits
  478. ;are zero, we treat the LSB as if it were a sticky bit. Thus if the LSB
  479. ;is set, that will always force a round up (to even) if the round bit is
  480. ;set. If the LSB is zero, then the sticky bits remain zero and we always
  481. ;round down.
  482. bt ebx,0 ;Look at LSB (for round even)
  483. adc edx,-1 ;CY set if sticky bits <>0
  484. adc edi,(1 shl 31)-1 ;CY set if round up
  485. jnc StoreIEEE32Int
  486. mov EMSEG:[SWcc],RoundUp
  487. inc ebx
  488. jz Over32Int
  489. StoreIEEE32Int:
  490. cmp ebx,1 shl 31 ;Check for max value
  491. jae CheckMax32
  492. SignAndStore32Int:
  493. shl eax,24 ;Sign to MSB
  494. cdq ;Extend sign through edx
  495. xor ebx,edx ;Complement
  496. sub ebx,edx ; and increment if negative
  497. clc
  498. Store32Int:
  499. mov dseg:[esi],ebx
  500. ;CY clear indicates no error
  501. ret
  502. Under32Int:
  503. ;ZF set if exponent is -1
  504. xchg edx,edi ;32-bit right shift
  505. xchg edi,ebx ;ebx = 0 now
  506. jz Round32Int ;If exponent was -1, ready to round
  507. mov EMSEG:[CURerr],Precision ;Set flag on inexact result
  508. NotNearest32Int:
  509. ;We want to increase the magnitude if RCup and +, or RCdown and -
  510. mov ah,EMSEG:[CWcntl] ;Get rounding control
  511. sar al,7 ;Expand sign through whole byte
  512. .erre (not RCup and RoundControl) eq RCdown
  513. xor ah,al ;Flip rounding bits if negative
  514. and ah,RoundControl
  515. cmp ah,RCup ;Rounding up?
  516. jnz StoreIEEE32Int ;No, chop it
  517. mov EMSEG:[SWcc],RoundUp
  518. inc ebx
  519. jnc StoreIEEE32Int
  520. jmp Over32Int
  521. ;*******************************************************************************
  522. StoreSpcl16Int:
  523. cmp cl,bTAG_DEN
  524. jz NormStore16Int ;Ignore denormal
  525. cmp cl,bTAG_EMPTY
  526. jnz Over16Int ;All other specials are invalid
  527. mov EMSEG:[CURerr],StackFlag+Invalid
  528. jmp Invalid16Int
  529. DoNothing16Int:
  530. stc ;Don't pop stack
  531. ret
  532. CheckMax16:
  533. ja Over16Int
  534. test al,bSign ;Is it negative?
  535. jnz Store16Int ;If so, answer is OK
  536. Over16Int:
  537. ;Overflow on integer store is invalid according to IEEE
  538. mov EMSEG:[CURerr],Invalid
  539. Invalid16Int:
  540. test EMSEG:[CWmask],Invalid ;Is it masked?
  541. jz DoNothing16Int ;No--leave memory unchanged
  542. ;Store Indefinite
  543. ;For FSTP, we go ahead and do the pop even though it's empty
  544. mov word ptr dseg:[esi],8000H ;16-bit integer indefinite
  545. ret ;CY clear
  546. ;*******************
  547. ;Store Short Integer
  548. ;*******************
  549. EM_ENTRY eFISTP16
  550. eFISTP16:
  551. push offset PopStackChk ;Return here after store
  552. EM_ENTRY eFIST16
  553. eFIST16:
  554. mov EMSEG:[PrevDataOff],esi ;Save operand pointer
  555. mov ebx,EMSEG:[edi].lManHi
  556. mov ecx,EMSEG:[edi].ExpSgn
  557. mov edi,EMSEG:[edi].lManLo
  558. ;mantissa in ebx:edi, exponent in high ecx, sign in ch bit 7, tag in cl
  559. ;memory destination is dseg:esi
  560. mov al,ch ;Save sign bit
  561. cmp cl,bTAG_ZERO
  562. .erre bTAG_VALID lt bTAG_ZERO
  563. .erre bTAG_SNGL lt bTAG_ZERO
  564. jz Store16Int ;Just store zero and exit
  565. ja StoreSpcl16Int
  566. NormStore16Int:
  567. xor edx,edx
  568. sar ecx,16 ;Bring exponent down
  569. cmp ecx,-1 ;Is it less than 1?
  570. jle Under16Int
  571. cmp ecx,15
  572. jg Over16Int
  573. sub ecx,31
  574. neg ecx ;cl = amount to shift right
  575. shrd edx,edi,cl
  576. shrd edi,ebx,cl ;Collect round and sticky bits
  577. shr ebx,cl ;Align integer
  578. ;See if we need to round
  579. mov ecx,edi
  580. or ecx,edx ;Throwing away any bits?
  581. jz StoreIEEE16Int
  582. ;Result will not be exact--check rounding mode
  583. Round16Int:
  584. mov EMSEG:[CURerr],Precision ;Set flag on inexact result
  585. test EMSEG:[CWcntl],RoundControl ;Check rounding control bits
  586. .erre RCnear eq 0
  587. jnz NotNearest16Int ;Not just round-to-nearest
  588. ;To perform "round even" when the round bit is set and the sticky bits
  589. ;are zero, we treat the LSB as if it were a sticky bit. Thus if the LSB
  590. ;is set, that will always force a round up (to even) if the round bit is
  591. ;set. If the LSB is zero, then the sticky bits remain zero and we always
  592. ;round down.
  593. bt ebx,0 ;Look at LSB (for round even)
  594. adc edx,-1 ;CY set if sticky bits <>0
  595. adc edi,(1 shl 31)-1 ;CY set if round up
  596. jnc StoreIEEE16Int
  597. mov EMSEG:[SWcc],RoundUp
  598. inc ebx
  599. StoreIEEE16Int:
  600. cmp ebx,1 shl 15 ;Check for max value
  601. jae CheckMax16
  602. SignAndStore16Int:
  603. shl eax,24 ;Sign to MSB
  604. cdq ;Extend sign through edx
  605. xor ebx,edx ;Complement
  606. sub ebx,edx ; and increment if negative
  607. clc
  608. Store16Int:
  609. mov dseg:[esi],bx
  610. ;CY clear indicates no error
  611. ret
  612. Under16Int:
  613. ;ZF set if exponent is -1
  614. xchg edx,edi ;16-bit right shift
  615. xchg edi,ebx ;ebx = 0 now
  616. jz Round16Int ;If exponent was -1, ready to round
  617. mov EMSEG:[CURerr],Precision ;Set flag on inexact result
  618. NotNearest16Int:
  619. ;We want to increase the magnitude if RCup and +, or RCdown and -
  620. mov ah,EMSEG:[CWcntl] ;Get rounding control
  621. sar al,7 ;Expand sign through whole byte
  622. .erre (not RCup and RoundControl) eq RCdown
  623. xor ah,al ;Flip rounding bits if negative
  624. and ah,RoundControl
  625. cmp ah,RCup ;Rounding up?
  626. jnz StoreIEEE16Int ;No, chop it
  627. mov EMSEG:[SWcc],RoundUp
  628. inc ebx
  629. jnc StoreIEEE16Int
  630. jmp Over16Int
  631. ;*******************************************************************************
  632. ;******************
  633. ;Store Quad Integer
  634. ;******************
  635. EM_ENTRY eFISTP64
  636. eFISTP64:
  637. mov EMSEG:[PrevDataOff],esi ;Save operand pointer
  638. call RoundToInteger
  639. jc Invalid64Int
  640. ;Have integer in ebx:edi
  641. ;Sign in ch
  642. cmp ebx,1 shl 31 ;Check for max value
  643. jae CheckMax64
  644. or ch,ch ;Check sign
  645. jns Store64Int
  646. ;64-bit negation
  647. not ebx
  648. neg edi
  649. sbb ebx,-1
  650. Store64Int:
  651. mov dseg:[esi],edi
  652. mov dseg:[esi+4],ebx
  653. jmp PopStack
  654. CheckMax64:
  655. ja Over64Int
  656. test al,bSign ;Is it negative?
  657. jnz Store64Int ;If so, answer is OK
  658. Over64Int:
  659. ;Overflow on integer store is invalid according to IEEE
  660. mov EMSEG:[CURerr],Invalid
  661. Invalid64Int:
  662. test EMSEG:[CWmask],Invalid ;Is it masked?
  663. jz DoNothing80 ;No--leave memory unchanged
  664. ;Store Indefinite
  665. ;For FSTP, we go ahead and do the pop even though it's empty
  666. mov dword ptr dseg:[esi],0
  667. mov dword ptr dseg:[esi+4],80000000H ;64-bit integer indefinite
  668. jmp PopStack
  669. ;*******************************************************************************
  670. Empty80:
  671. ;It's empty--signal invalid operation
  672. mov EMSEG:[CURerr],StackFlag+Invalid
  673. test EMSEG:[CWmask],Invalid ;Is it masked?
  674. jz DoNothing80 ;No--leave memory unchanged
  675. ;Store Indefinite
  676. ;For FSTP, we go ahead and do the pop even though it's empty
  677. mov dword ptr dseg:[esi],0
  678. mov dword ptr dseg:[esi+4],0C0000000H
  679. mov word ptr dseg:[esi+8],0FFFFH ;80-bit IEEE indefinite
  680. jmp PopStack
  681. DoNothing80:
  682. ret
  683. ;***************
  684. ;Store Temp Real
  685. ;***************
  686. EM_ENTRY eFSTP80
  687. eFSTP80:
  688. mov EMSEG:[PrevDataOff],esi ;Save operand pointer
  689. mov eax,EMSEG:[edi].ExpSgn
  690. cmp al,bTAG_EMPTY
  691. jz Empty80
  692. push offset PopStack
  693. StoreTempReal:
  694. mov ebx,EMSEG:[edi].lManHi
  695. mov edi,EMSEG:[edi].lManLo
  696. ;mantissa in ebx:edi, exponent in high eax, sign in ah bit 7, tag in al
  697. ;memory destination is dseg:esi
  698. mov ecx,eax ;get copy of sign and tag
  699. shr ecx,16 ;Bring exponent down
  700. cmp al,bTAG_ZERO
  701. jz StoreIEEE80 ;Skip bias if zero
  702. add ecx,IexpBias-TexpBias ;Correct bias
  703. cmp al,bTAG_DEN
  704. jz Denorm80
  705. StoreIEEE80:
  706. and eax,bSign shl 8
  707. or ecx,eax ;Combine sign with exponent
  708. mov dseg:[esi],edi
  709. mov dseg:[esi+4],ebx
  710. mov dseg:[esi+8],cx
  711. ; jmp PopStack
  712. ret
  713. Denorm80:
  714. ;Must change it to a denormal
  715. dec ecx
  716. neg ecx ;Use as shift count
  717. cmp cl,32 ;Long shift?
  718. jae LongDenorm
  719. shrd edi,ebx,cl
  720. shr ebx,cl
  721. xor ecx,ecx ;Exponent is zero
  722. jmp StoreIEEE80
  723. LongDenorm:
  724. ;edi must be zero if we have 32 bits to shift
  725. xchg ebx,edi ;32-bit right shift
  726. shr edi,cl ;shift count is modulo-32
  727. xor ecx,ecx ;Exponent is zero
  728. jmp StoreIEEE80