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.

402 lines
10 KiB

  1. subttl emfcom.asm - Comparison Instructions
  2. page
  3. ;*******************************************************************************
  4. ;emfcom.asm - Comparison Instructions
  5. ;
  6. ; Microsoft Confidential
  7. ;
  8. ; Copyright (c) Microsoft Corporation 1991
  9. ; All Rights Reserved
  10. ;
  11. ;Purpose:
  12. ; FCOM,FCOMP,FCOMPP,FUCOM,FUCOMP,FUCOMPP,FTST,FXAM instructions
  13. ;
  14. ;Revision History:
  15. ;
  16. ; [] 09/05/91 TP Initial 32-bit version.
  17. ;
  18. ;*******************************************************************************
  19. ;*******************************************************************************
  20. ;Dispatch table for compare
  21. ;
  22. ;One operand has been loaded into ecx:ebx:esi ("source"), the other is
  23. ;pointed to by edi ("dest").
  24. ;
  25. ;Tag of source is shifted. Tag values are as follows:
  26. .erre TAG_SNGL eq 0 ;SINGLE: low 32 bits are zero
  27. .erre TAG_VALID eq 1
  28. .erre TAG_ZERO eq 2
  29. .erre TAG_SPCL eq 3 ;NAN, Infinity, Denormal, Empty
  30. ;Any special case routines not found in this file are in emarith.asm
  31. tFcomDisp label dword ;Source (reg) Dest (*[di] = ST)
  32. dd ComDouble ;single single
  33. dd ComDouble ;single double
  34. dd ComDestZero ;single zero
  35. dd ComSpclDest ;single special
  36. dd ComDouble ;double single
  37. dd ComDouble ;double double
  38. dd ComDestZero ;double zero
  39. dd ComSpclDest ;double special
  40. dd ComSrcZero ;zero single
  41. dd ComSrcZero ;zero double
  42. dd ComEqual ;zero zero
  43. dd ComSpclDest ;zero special
  44. dd ComSpclSource ;special single
  45. dd ComSpclSource ;special double
  46. dd ComSpclSource ;special zero
  47. dd ComBothSpcl ;special special
  48. EM_ENTRY eFICOMP16
  49. eFICOMP16:
  50. and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3
  51. push offset PopWhenDone
  52. push offset ComOpLoaded
  53. jmp Load16Int ;Returns to ComOpLoaded
  54. EM_ENTRY eFICOM16
  55. eFICOM16:
  56. and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3
  57. push offset ComOpLoaded
  58. jmp Load16Int ;Returns to ComOpLoaded
  59. EM_ENTRY eFICOMP32
  60. eFICOMP32:
  61. and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3
  62. push offset PopWhenDone
  63. push offset ComOpLoaded
  64. jmp Load32Int ;Returns to ComOpLoaded
  65. EM_ENTRY eFICOM32
  66. eFICOM32:
  67. and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3
  68. push offset ComOpLoaded
  69. jmp Load32Int ;Returns to ComOpLoaded
  70. EM_ENTRY eFCOMP32
  71. eFCOMP32:
  72. and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3
  73. push offset PopWhenDone
  74. push offset ComOpLoaded
  75. jmp Load32Real ;Returns to ComOpLoaded
  76. EM_ENTRY eFCOM32
  77. eFCOM32:
  78. and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3
  79. push offset ComOpLoaded
  80. jmp Load32Real ;Returns to ComOpLoaded
  81. EM_ENTRY eFCOMP64
  82. eFCOMP64:
  83. and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3
  84. push offset PopWhenDone
  85. push offset ComOpLoaded
  86. jmp Load64Real ;Returns to ComOpLoaded
  87. EM_ENTRY eFCOM64
  88. eFCOM64:
  89. and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3
  90. push offset ComOpLoaded
  91. jmp Load64Real ;Returns to ComOpLoaded
  92. EM_ENTRY eFUCOMPP
  93. eFUCOMPP:
  94. and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3
  95. push offset ComPop2
  96. jmp eFUCOM0
  97. EM_ENTRY eFUCOMP
  98. eFUCOMP:
  99. and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3
  100. push offset PopWhenDone
  101. jmp eFUCOM0
  102. EM_ENTRY eFUCOM
  103. eFUCOM:
  104. and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3
  105. eFUCOM0:
  106. ;esi = pointer to st(i) from instruction field
  107. ;edi = [CURstk]
  108. mov ecx,EMSEG:[esi].ExpSgn
  109. mov ebx,EMSEG:[esi].lManHi
  110. mov esi,EMSEG:[esi].lManLo
  111. mov dl,40H ;Flag FUCOM - Look for SNAN
  112. jmp UComOpLoaded
  113. EM_ENTRY eFCOMPP
  114. eFCOMPP:
  115. and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3
  116. push offset ComPop2
  117. jmp eFCOM0
  118. EM_ENTRY eFCOMP
  119. eFCOMP:
  120. and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3
  121. push offset PopWhenDone
  122. jmp eFCOM0
  123. EM_ENTRY eFCOM
  124. eFCOM:
  125. and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3
  126. eFCOM0:
  127. ;esi = pointer to st(i) from instruction field
  128. ;edi = [CURstk]
  129. mov ecx,EMSEG:[esi].ExpSgn
  130. mov ebx,EMSEG:[esi].lManHi
  131. mov esi,EMSEG:[esi].lManLo
  132. ComOpLoaded:
  133. ; mov EMSEG:[UpdateCCodes],1
  134. mov dl,0 ;flag FCOM - Look for any NAN
  135. UComOpLoaded:
  136. mov ebp,offset tFcomDisp
  137. mov al,cl
  138. mov ah,EMSEG:[edi].bTag
  139. test ax,ZEROorSPCL * 100H + ZEROorSPCL
  140. jnz TwoOpDispatch
  141. ;.erre ComDouble eq $ ;Fall into ComDouble
  142. ;*********
  143. ComDouble:
  144. ;*********
  145. ;
  146. ;ebx:esi = op1 mantissa
  147. ;ecx = op1 sign in bit 15, exponent in high half
  148. ;edi = pointer to op2
  149. mov eax,EMSEG:[edi].ExpSgn
  150. and ax,bSign shl 8 ;Keep sign only
  151. and cx,bSign shl 8
  152. cmp ah,ch ;Are signs the same?
  153. jnz StBigger
  154. cmp eax,ecx ;Are exponents the same?
  155. jl StSmaller
  156. jg StBigger
  157. cmp EMSEG:[edi].lManHi,ebx ;Compare mantissas
  158. jnz MantDif
  159. cmp EMSEG:[edi].lManLo,esi ;Set flags for ST - src
  160. jz ComEqual
  161. MantDif:
  162. adc al,al ;Copy CY flag to bit 0
  163. rol ah,1 ;Rotate sign to bit 0
  164. xor al,ah ;Flip saved CY bit if negative
  165. mov EMSEG:[SWcc],al ;Set condition code
  166. ret
  167. StSmaller:
  168. not ah
  169. StBigger:
  170. ;ah = sign of ST
  171. ;ch = sign of other operand
  172. ;ST is bigger if it is positive (smaller if it is negative).
  173. ;Use the sign bit directly as the "less than" bit C0.
  174. .erre C0 eq 1
  175. shr ah,7 ;Bring sign down to bit 0, clear CY
  176. mov EMSEG:[SWcc],ah ;Bit set if ST smaller (negative)
  177. ret
  178. ComEqual:
  179. mov EMSEG:[SWcc],CCequal
  180. ret
  181. PopWhenDone:
  182. .erre bTAG_NOPOP eq -1
  183. inc cl ;OK to pop?
  184. jz ComPopX ;No - had unmasked Invalid Operation
  185. POPSTret
  186. ComPop2:
  187. .erre bTAG_NOPOP eq -1
  188. inc cl ;OK to pop?
  189. jz ComPopX ;No - had unmasked Invalid Operation
  190. mov esi,EMSEG:[CURstk]
  191. mov EMSEG:[esi].bTag,bTAG_EMPTY
  192. add esi,Reg87Len*2
  193. cmp esi,ENDstk ;JWM
  194. je PopOneOver
  195. ja PopTwoOver
  196. mov EMSEG:[esi-Reg87Len].bTag,bTAG_EMPTY
  197. mov EMSEG:[CURstk],esi
  198. ComPopX:
  199. ret
  200. PopOneOver:
  201. mov EMSEG:[CURstk],BEGstk ;JWM
  202. ifdef NT386
  203. mov EMSEG:[INITstk].bTAG,bTAG_EMPTY
  204. else
  205. mov EMSEG:[XINITstk].bTAG,bTAG_EMPTY
  206. endif
  207. ret
  208. PopTwoOver:
  209. mov EMSEG:[CURstk],BEGstk+Reg87Len ;JWM
  210. ifdef NT386
  211. mov EMSEG:[BEGstk].bTAG,bTAG_EMPTY
  212. else
  213. mov EMSEG:[XBEGstk].bTAG,bTAG_EMPTY
  214. endif
  215. ret
  216. ;*******************************************************************************
  217. ;Special cases for FCOM/FUCOM.
  218. ;These don't share with those in emarith.asm because NANs are treated
  219. ;differently.
  220. ComDestZero:
  221. ;ST is zero, so Src is bigger if it is positive (smaller if it is negative).
  222. ;Use the sign bit directly as the "less than" bit C0.
  223. not ch ;C0 is 1 if ST < Src
  224. .erre C0 eq 1
  225. shr ch,7 ;Bring sign down to bit 0
  226. mov EMSEG:[SWcc],ch ;Bit set if Src smaller (negative)
  227. ret
  228. ComSrcZero:
  229. ;ST is bigger if it is positive (smaller if it is negative).
  230. ;Use the sign bit directly as the "less than" bit C0.
  231. mov al,EMSEG:[edi].bSgn
  232. .erre C0 eq 1
  233. shr al,7 ;Bring sign down to bit 0
  234. mov EMSEG:[SWcc],al ;Bit set if ST smaller (negative)
  235. ret
  236. ComSpclSource:
  237. cmp cl,bTAG_NAN
  238. jz ComSrcNAN
  239. cmp cl,bTAG_INF
  240. jz ComDestZero
  241. cmp cl,bTAG_DEN
  242. jz ComDenormal
  243. ;Must be empty
  244. ComEmpty:
  245. mov EMSEG:[CURerr],Invalid+StackFlag
  246. jmp ComChkMask
  247. ComSrcNAN:
  248. shl edx,24 ;Move dl to high byte
  249. test ebx,edx ;See if we report error with this NAN
  250. ComChkNAN:
  251. jnz Incomp
  252. ComInvalid:
  253. mov EMSEG:[CURerr],Invalid ;Flag the error
  254. ComChkMask:
  255. test EMSEG:[CWmask],Invalid ;Is exception masked?
  256. jnz Incomp
  257. mov cl,bTAG_NOPOP ;Unmasked, don't pop stack
  258. Incomp:
  259. mov EMSEG:[SWcc],CCincomprable
  260. ret
  261. ComSpclDest:
  262. mov al,EMSEG:[edi].bTag
  263. cmp al,bTAG_INF
  264. jz ComSrcZero
  265. cmp al,bTAG_Empty
  266. jz ComEmpty
  267. cmp al,bTAG_DEN
  268. jz ComDenormal
  269. ;Must be NAN
  270. ComDestNAN:
  271. test EMSEG:[edi].bMan7,dl ;See if we report error with this NAN
  272. jmp ComChkNAN
  273. ComBothSpcl:
  274. mov al,EMSEG:[edi].bTag
  275. cmp cl,bTAG_EMPTY
  276. jz ComEmpty
  277. cmp al,bTAG_EMPTY
  278. jz ComEmpty
  279. cmp cl,bTAG_NAN
  280. jz ComSrcNAN
  281. cmp al,bTAG_NAN
  282. jz ComDestNAN
  283. mov ah,cl
  284. cmp ax,(bTAG_INF shl 8) + bTag_INF ;Are both Infinity?
  285. jz ComDouble ;If so, compare their signs
  286. ;Must have at least one denormal
  287. ComDenormal:
  288. or EMSEG:[CURerr],Denormal
  289. jmp ComDouble
  290. ;*******************************************************************************
  291. XAM_Unsupported equ 0
  292. XAM_NAN equ C0
  293. XAM_Norm equ C2
  294. XAM_Inf equ C2+C0
  295. XAM_Zero equ C3
  296. XAM_Empty equ C3+C0
  297. XAM_Den equ C3+C2
  298. tXamTag label byte
  299. .erre TAG_SNGL eq $-tXamTag
  300. db XAM_Norm ;TAG_SNGL
  301. .erre TAG_VALID eq $-tXamTag
  302. db XAM_Norm ;TAG_VALID
  303. .erre TAG_ZERO eq $-tXamTag
  304. db XAM_Zero ;TAG_ZERO
  305. .erre TAG_EMPTY eq $-tXamTag
  306. db XAM_Empty ;TAG_EMPTY
  307. db 0
  308. db 0
  309. db 0
  310. .erre TAG_INF eq $-tXamTag
  311. db XAM_Inf ;TAG_INF
  312. db 0
  313. db 0
  314. db 0
  315. .erre TAG_NAN eq $-tXamTag
  316. db XAM_NAN ;TAG_NAN
  317. db 0
  318. db 0
  319. db 0
  320. .erre TAG_DEN eq $-tXamTag
  321. db XAM_Den ;TAG_DEN
  322. EM_ENTRY eFXAM
  323. eFXAM:
  324. ;edi = [CURstk]
  325. and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3
  326. mov eax,EMSEG:[edi].ExpSgn ;Get sign and tag
  327. mov bl,ah ;Save sign
  328. and bl,bSign ;Keep only sign bit
  329. and eax,0FH ;Save low 4 bits of tag
  330. mov al,tXamTag[eax] ;Lookup cond. codes for this tag
  331. .erre C1 eq 2 ;Bit 1
  332. .erre bSign eq 80H ;Bit 7
  333. shr bl,7-1 ;Move sign bit to CC C1
  334. or al,bl
  335. mov EMSEG:[SWcc],al
  336. ret
  337. ;*******************************************************************************
  338. EM_ENTRY eFTST
  339. eFTST:
  340. ;edi = [CURstk]
  341. and [esp].[OldLongStatus+4],NOT(ConditionCode SHL 16) ;clear C0,C1,C2,C3
  342. mov eax,EMSEG:[edi].ExpSgn
  343. cmp al,bTAG_ZERO
  344. jz ComEqual
  345. ja TestSpcl
  346. ;Either single or double, non-zero. Just check sign.
  347. TestSign:
  348. shr ah,7 ;Bring sign down to bit 0
  349. mov EMSEG:[SWcc],ah ;Bit set if negative
  350. ret
  351. TestSpcl:
  352. cmp al,bTAG_INF
  353. jz TestSign ;Normal test for Infinity
  354. cmp al,bTAG_EMPTY
  355. jz ComEmpty
  356. cmp al,bTAG_NAN
  357. jz ComInvalid
  358. ;Must be denormal
  359. mov EMSEG:[CURerr],Denormal
  360. jmp TestSign