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.

457 lines
11 KiB

  1. subttl emlsenv.asm - Emulator Save/Restore
  2. page
  3. ;***
  4. ;emlsenv.asm - Emulator Save/Restore
  5. ;
  6. ;
  7. ; Copyright (c) Microsoft Corporation 1991
  8. ;
  9. ; All Rights Reserved
  10. ;
  11. ;Purpose:
  12. ; FLDCW, FSTCW, FSTSW, FSTENV, FLDENV, FSAVE, FRSTOR instructions
  13. ;
  14. ;Revision History:
  15. ;
  16. ; [] 09/05/91 TP Initial 32-bit version.
  17. ;
  18. ;
  19. ;*******************************************************************************
  20. ;When setting the control word, the [RoundMode] vector must be set
  21. ;according to the rounding and precision modes.
  22. tRoundMode label dword
  23. irp RC,<near,down,up,chop>
  24. irp PC,<24,24,53,64>
  25. dd Round&&PC&&RC
  26. endm
  27. endm
  28. EM_ENTRY eFLDCW
  29. eFLDCW:
  30. ;Uses only eax and ebx
  31. mov ax, dseg:[esi] ; Fetch control word from user memory
  32. SetControlWord:
  33. and ax,0F3FH ; Limit to valid values
  34. mov EMSEG:[ControlWord], ax ; Store in the emulated control word
  35. not al ;Flip mask bits for fast compare
  36. and al,3FH ;Limit to valid mask bits
  37. mov EMSEG:[ErrMask],al
  38. and eax,(RoundControl + PrecisionControl) shl 8
  39. .erre RoundControl eq 1100B
  40. .erre PrecisionControl eq 0011B
  41. shr eax,6 ;Put PC and RC in bits 2-5
  42. mov ebx,tRoundMode[eax] ;Get correct RoundMode vector
  43. mov EMSEG:[RoundMode],ebx
  44. mov EMSEG:[SavedRoundMode],ebx
  45. and eax,RoundControl shl (8-6) ;Mask off precision control
  46. mov ebx,tRoundMode[eax+PC64 shl (8-6)];Get correct RoundMode vector
  47. mov EMSEG:[TransRound],ebx ;Round mode w/o precision
  48. ret
  49. EM_ENTRY eFSTCW
  50. eFSTCW:
  51. ;Uses only eax
  52. mov ax, EMSEG:[ControlWord] ; Fetch user control word
  53. mov dseg:[esi], ax ; Store into user memory
  54. ret
  55. EM_ENTRY eFSTSW
  56. eFSTSW:
  57. ;Uses only eax and ebx
  58. call GetStatusWord ; Fetch emulated Status word
  59. mov dseg:[esi], ax ; Store into user memory
  60. ret
  61. eFSTSWax:
  62. ;Uses only eax and ebx
  63. call GetStatusWord ; Fetch emulated Status word
  64. mov [esp+4].regAX,ax
  65. ret
  66. EM_ENTRY eFDECSTP
  67. eFDECSTP:
  68. ;edi = [CURstk]
  69. cmp edi,BEGstk
  70. jbe DecWrap
  71. sub EMSEG:[CURstk],Reg87Len
  72. ret
  73. DecWrap:
  74. mov EMSEG:[CURstk],INITstk
  75. ret
  76. EM_ENTRY eFINCSTP
  77. eFINCSTP:
  78. ;edi = [CURstk]
  79. cmp edi,INITstk
  80. jae IncWrap
  81. add EMSEG:[CURstk],Reg87Len
  82. ret
  83. IncWrap:
  84. mov EMSEG:[CURstk],BEGstk
  85. ret
  86. eFCLEX:
  87. mov EMSEG:[SWerr],0
  88. and [esp+4].OldLongStatus,0FFFF00FFH ; clear saved SWerr
  89. ret
  90. ;*** eFSTENV - emulate FSTENV [address]
  91. ;
  92. ; ARGUMENTS
  93. ; dseg:esi = where to store environment
  94. ;
  95. ;
  96. ; DESCRIPTION
  97. ; This routine emulates an 80387 FSTENV (store environment)
  98. ;
  99. EM_ENTRY eFSTENV
  100. eFSTENV:
  101. mov ax,[esp+4].OldStatus
  102. mov EMSEG:[StatusWord],ax
  103. SaveEnv:
  104. xor ax,ax
  105. mov dseg:[esi.reserved1],ax
  106. mov dseg:[esi.reserved2],ax
  107. mov dseg:[esi.reserved3],ax
  108. mov dseg:[esi.reserved4],ax
  109. mov dseg:[esi.reserved5],ax
  110. mov ax,EMSEG:[ControlWord]
  111. mov dseg:[esi.E32_ControlWord],ax
  112. call GetEMSEGStatusWord
  113. mov dseg:[esi.E32_StatusWord],ax
  114. call GetTagWord
  115. mov dseg:[esi.E32_TagWord],ax
  116. mov ax,cs
  117. mov dseg:[esi.E32_CodeSeg],ax
  118. mov ax,ss
  119. mov dseg:[esi.E32_DataSeg],ax
  120. mov eax,EMSEG:[PrevCodeOff]
  121. mov dseg:[esi.E32_CodeOff],eax
  122. mov eax,EMSEG:[PrevDataOff]
  123. mov dseg:[esi.E32_DataOff],eax
  124. mov EMSEG:[CWmask],03FH ;Set all mask bits
  125. mov EMSEG:[ErrMask],0
  126. ret
  127. ;*** eFSAVE - emulate FSAVE [address]
  128. ;
  129. ; ARGUMENTS
  130. ; dseg:esi = where to store environment
  131. ;
  132. ;
  133. ; DESCRIPTION
  134. ; This routine emulates an 80387 FSAVE (store environment)
  135. ; Once the data is stored an finit is executed.
  136. ;
  137. ; REGISTERS
  138. ; destroys ALL.
  139. EM_ENTRY eFSAVE
  140. eFSAVE:
  141. mov ax,[esp+4].OldStatus
  142. mov EMSEG:[StatusWord],ax
  143. mov eax,[esp+4].OldCodeOff
  144. mov EMSEG:[PrevCodeOff],eax
  145. push offset eFINIT ; After fsave we must do a finit
  146. SaveState: ; Enter here for debugger save state
  147. call SaveEnv
  148. add esi,size Env80x87_32 ;Skip over environment
  149. mov ebp,NumLev ;Save entire stack
  150. mov edi,EMSEG:[CURstk]
  151. FsaveStoreLoop:
  152. mov eax,EMSEG:[edi].ExpSgn
  153. call StoreTempReal ;in emstore.asm
  154. add esi,10
  155. mov edi,EMSEG:[CURstk]
  156. NextStackElem edi,FSave
  157. mov EMSEG:[CURstk],edi
  158. dec ebp
  159. jnz FsaveStoreLoop
  160. ret
  161. WrapFSave: ; tied to NextStackElem above
  162. mov edi, BEGstk
  163. mov EMSEG:[CURstk],edi
  164. dec ebp
  165. jnz FsaveStoreLoop
  166. ret
  167. ;*** eFRSTOR - emulate FRSTOR [address]
  168. ;
  169. ; ARGUMENTS
  170. ; dseg:esi = where to get the environment
  171. ;
  172. ; DESCRIPTION
  173. ; This routine emulates an 80387 FRSTOR (restore state)
  174. NextStackWrap edi,Frstor
  175. EM_ENTRY eFRSTOR
  176. eFRSTOR:
  177. ;First we set up the status word so that [CURstk] is initialized.
  178. ;The floating-point registers are stored in logical ST(0) - ST(7) order,
  179. ;not physical register order. We don't do a full load of the environment
  180. ;because we're not ready to use the tag word yet.
  181. and [esp+4].[OldLongStatus], NOT(LongSavedFlags) ;clear saved codes, errs
  182. mov ax, dseg:[esi.E32_StatusWord]
  183. call SetEmStatusWord ;Initialize [CURstk]
  184. add esi,size Env80x87_32 ;Skip over environment
  185. ;Load of temp real has one difference from real math chip: it is an invalid
  186. ;operation to load an unsupported format. By ensuring the exception is
  187. ;masked, we will convert unsupported format to Indefinite. Note that the
  188. ;mask and [CURerr] will be completely restored by the FLDENV at the end.
  189. mov EMSEG:[CWmask],3FH ;Mask off invalid operation exception
  190. mov edi,EMSEG:[CURstk]
  191. mov ebp,NumLev
  192. FrstorLoadLoop:
  193. push esi
  194. call LoadTempReal ;In emload.asm
  195. pop esi
  196. add esi,10 ;Point to next temp real
  197. NextStackElem edi,Frstor
  198. dec ebp
  199. jnz FrstorLoadLoop
  200. sub esi,NumLev*10+size Env80x87_32 ;Point to start of env.
  201. jmp eFLDENV ;Fall into eFLDENV
  202. ;*** eFLDENV - emulate FLDENV [address]
  203. ;
  204. ; ARGUMENTS
  205. ; dseg:si = where to store environment
  206. ;
  207. ; This routine emulates an 80387 FLDENV (load environment)
  208. EM_ENTRY eFLDENV
  209. eFLDENV:
  210. and [esp+4].[OldLongStatus], NOT(LongSavedFlags) ;clear saved codes, errs
  211. mov ax, dseg:[esi.E32_StatusWord]
  212. call SetEmStatusWord ; set up status word
  213. mov ax, dseg:[esi.E32_ControlWord]
  214. call SetControlWord
  215. mov ax, dseg:[esi.E32_TagWord]
  216. call UseTagWord
  217. mov eax, dseg:[esi.E32_CodeOff]
  218. mov EMSEG:[PrevCodeOff], eax
  219. mov eax, dseg:[esi.E32_DataOff]
  220. mov EMSEG:[PrevDataOff], eax
  221. ret
  222. ;*** GetTagWord - figures out what the tag word is from the numeric stack
  223. ; and returns the value of the tag word in ax.
  224. ;
  225. GetTagWord:
  226. push esi
  227. xor eax, eax
  228. mov ecx, NumLev ; get tags for regs. 0, 7 - 1
  229. mov esi,INITstk
  230. GetTagLoop:
  231. mov bh, EMSEG:[esi.bTag] ; The top 2 bits of Tag are the X87 tag bits.
  232. shld ax, bx, 2
  233. sub esi, Reg87Len
  234. loop GetTagLoop
  235. rol ax, 2 ; This moves Tag(0) into the low 2 bits
  236. pop esi
  237. ret
  238. ;*** UseTagWord - Set up tags using tag word from environment
  239. ;
  240. ; ARGUMENTS
  241. ; ax - should contain the tag word
  242. ;
  243. ; Destroys ax,bx,cx,dx,di
  244. UseTagWord:
  245. ror ax, 2 ; mov Tag(0) into top bits of ax
  246. mov edi,INITstk
  247. mov ecx, NumLev
  248. UseTagLoop:
  249. mov dl,bTAG_EMPTY
  250. cmp ah, 0c0h ;Is register to be tagged Empty?
  251. jae SetTag ;Yes, go mark it
  252. mov dl,EMSEG:[edi].bTag ;Get current tag
  253. cmp dl,bTAG_EMPTY ;Is register currently Empty?
  254. je SetTagNotEmpty ;If so, go figure out tag for it
  255. SetTag:
  256. mov EMSEG:[edi].bTag,dl
  257. UseTagLoopCheck:
  258. sub edi, Reg87Len
  259. shl eax, 2
  260. loop UseTagLoop
  261. ret
  262. SetTagEmpty:
  263. mov EMSEG:[edi.bTag], bTAG_EMPTY
  264. jmp UseTagLoopCheck
  265. SetTagNotEmpty:
  266. ;Register is currently tagged empty, but new tag word says it is not empty.
  267. ;Figure out a new tag for it. The rules are:
  268. ;
  269. ;1. Everything is either normalized or zero--unnormalized formats cannot
  270. ;get in. So if the high half mantissa is zero, the number is zero.
  271. ;
  272. ;2. Although the exponent bias is different, NANs and Infinities are in
  273. ;standard IEEE format - exponent is TexpMax, mantissa indicates NAN vs.
  274. ;infinity (mantissa for infinity is 800..000H).
  275. ;
  276. ;3. Denormals have an exponent less than TexpMin.
  277. ;
  278. ;4. If the low half of the mantissa is zero, it is tagged bTAG_SNGL
  279. ;
  280. ;5. Everything else is bTAG_VALID
  281. mov ebx,EMSEG:[edi].lManHi
  282. mov dl,bTAG_ZERO ;Try zero first
  283. or ebx,ebx ;Is mantissa zero?
  284. jz SetTag
  285. mov edx,EMSEG:[edi].ExpSgn
  286. mov dl,bTAG_DEN
  287. cmp edx,TexpMin shl 16 ;Is it denormal?
  288. jl SetTag
  289. cmp EMSEG:[edi].lManLo,0 ;Is low half zero?
  290. .erre bTAG_VALID eq 1
  291. .erre bTAG_SNGL eq 0
  292. setnz dl ;if low half==0 then dl=0 else dl=1
  293. cmp edx,TexpMax shl 16 ;Is it NAN or Infinity?
  294. jl SetTag ;If not, it's valid
  295. .erre (bTAG_VALID - bTAG_SNGL) shl TAG_SHIFT eq (bTAG_NAN - bTAG_INF)
  296. shl dl,TAG_SHIFT
  297. add dl,bTAG_INF - bTAG_SNGL
  298. ;If the low bits were zero we have just changed bTAG_SNGL to bTAG_INF
  299. ;If the low bits weren't zero, we changed bTAG_VALID to bTAG_NAN
  300. ;See if infinity is really possible: is high half 80..00H?
  301. cmp ebx,1 shl 31 ;Is it infinity?
  302. jz SetTag ;Store tag for infinity or NAN
  303. mov dl,bTAG_NAN
  304. jmp SetTag
  305. ;*** GetStatusWord -
  306. ;
  307. ; User status word returned in ax.
  308. ; Destroys ebx only.
  309. GetStatusWord:
  310. mov eax, EMSEG:[CURstk]
  311. sub eax, BEGstk
  312. mov bl,Reg87Len
  313. div bl
  314. inc eax ; adjust for emulator's stack layout
  315. and eax, 7 ; eax is now the stack number
  316. shl ax, 11
  317. or ax,[esp+8].OldStatus ; or in the rest of the status word.
  318. ret
  319. ;*** GetEMSEGStatusWord -
  320. ;
  321. ; User status word returned in ax.
  322. ; Destroys ebx only.
  323. ; Uses status word in per-thread data area, otherwise
  324. ; identical to GetStatusWord
  325. EM_ENTRY eGetStatusWord
  326. GetEMSEGStatusWord:
  327. mov eax, EMSEG:[CURstk]
  328. sub eax, BEGstk
  329. mov bl,Reg87Len
  330. div bl
  331. inc eax ; adjust for emulator's stack layout
  332. and eax, 7 ; eax is now the stack number
  333. shl ax, 11
  334. or ax, EMSEG:[StatusWord] ; or in the rest of the status word.
  335. ret
  336. ;*** SetEmStatusWord -
  337. ;
  338. ; Given user status word in ax, set into emulator.
  339. ; Destroys ebx only.
  340. SetEmStatusWord:
  341. and ax,7F7FH
  342. mov bx,ax
  343. and bx,3FH ; set up CURerr in case user
  344. mov EMSEG:[CURerr],bl ; wants to force an exception
  345. mov ebx, eax
  346. and ebx, not (7 shl 11) ; remove stack field.
  347. mov EMSEG:[StatusWord], bx
  348. sub ah, 8 ; adjust for emulator's stack layout
  349. and ah, 7 shl 3
  350. mov al, ah
  351. shr ah, 1
  352. add al, ah ; stack field * 3 * 4
  353. .erre Reg87Len eq 12
  354. and eax, 255 ; eax is now 12*stack number
  355. add eax, BEGstk
  356. mov EMSEG:[CURstk], eax
  357. ret
  358. public _SaveEm87Context
  359. _SaveEm87Context PROC
  360. push ebp
  361. mov ebp, esp
  362. push ebx
  363. push edi
  364. push esi
  365. mov esi, [ebp+8]
  366. call SaveState
  367. test EMSEG:[CURErr], Summary
  368. jne RetSaveEmIdle
  369. mov eax, Em87Busy
  370. jmp RetSaveEm
  371. RetSaveEmIdle:
  372. mov eax, Em87Idle
  373. RetSaveEm:
  374. pop esi
  375. pop edi
  376. pop ebx
  377. pop ebp
  378. ret
  379. _SaveEm87Context ENDP
  380. public _RestoreEm87Context
  381. _RestoreEm87Context PROC
  382. push ebp
  383. mov ebp, esp
  384. push ebx
  385. push edi
  386. push esi
  387. mov esi, [ebp+8]
  388. call eFRSTOR
  389. pop esi
  390. pop edi
  391. pop ebx
  392. pop ebp
  393. ret
  394. _RestoreEm87Context ENDP