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.

658 lines
21 KiB

  1. page 78,132
  2. ;*******************************************************************************
  3. ; Copyright (c) Microsoft Corporation 1991
  4. ; All Rights Reserved
  5. ;
  6. ; ke\i386\emxcptn.asm
  7. ;
  8. ; Module to support getting/setting context to and from the R3
  9. ; emulator.
  10. ;
  11. ;Revision History:
  12. ;
  13. ;
  14. ;*******************************************************************************
  15. .386p
  16. _TEXT SEGMENT DWORD PUBLIC 'CODE'
  17. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  18. ;;*******************************************************************************
  19. ;;
  20. ;; Include some more macros and constants.
  21. ;;
  22. ;;*******************************************************************************
  23. ;
  24. NT386 equ 1
  25. include ks386.inc
  26. include em387.inc ; Emulator TEB data layout
  27. include callconv.inc
  28. include irqli386.inc
  29. EXTRNP _KeBugCheck,1
  30. EXTRNP _ExRaiseStatus,1
  31. extrn _Ki387RoundModeTable:dword
  32. subttl _KiEm87StateToNpxFrame
  33. page
  34. ;*** _KiEm87StateToNpxFrames
  35. ;
  36. ; Translates the R3 emulators state to the NpxFrame
  37. ;
  38. ; Returns TRUE if NpxFrame sucessfully completed.
  39. ; else FALSE
  40. ;
  41. ; Warning: This function can only be called at Irql 0 with interrupts
  42. ; enabled. It is intended to be called only to deal with R3 exceptions
  43. ; when the emulator is being used.
  44. ;
  45. ; Revision History:
  46. ;
  47. ;
  48. ;*******************************************************************************
  49. cPublicProc _KiEm87StateToNpxFrame, 1
  50. push ebp
  51. mov ebp, esp
  52. push ebx ; Save C runtime varibles
  53. push edi
  54. push esi
  55. push esp ; Pass current Esp to handler
  56. push offset stnpx_30 ; Set Handler address
  57. push PCR[PcExceptionList] ; Set next pointer
  58. mov PCR[PcExceptionList],esp ; Link us on
  59. if DBG
  60. pushfd ; Sanity check
  61. pop ecx ; make sure interrupts are enabled
  62. test ecx, EFLAGS_INTERRUPT_MASK
  63. jz short stnpx_err
  64. CurrentIrql ; Sanity check
  65. cmp al, DISPATCH_LEVEL ; make sure Irql is below DPC level
  66. jnc short stnpx_err
  67. endif
  68. xor eax, eax ; set FALSE
  69. mov ebx,PCR[PcPrcbData+PbCurrentThread]
  70. mov ebx,[ebx]+ThApcState+AsProcess
  71. cmp dword ptr [ebx]+PrVdmObjects,0 ; is this a vdm process?
  72. jne short stnpx_10 ; Yes, then not supported
  73. mov ebx, PCR[PcTeb] ; R3 Teb
  74. cmp [ebx].Einstall, 0 ; Initialized?
  75. je short stnpx_10 ; No, then don't return NpxFrame
  76. test [ebx].CURErr, Summary ; Completed?
  77. jz short stnpx_10 ; No, then don't return NpxFrame
  78. mov esi, [ebp+8] ; (esi) = NpxFrame
  79. call SaveState
  80. mov eax, 1 ; Return TRUE
  81. stnpx_10:
  82. pop PCR[PcExceptionList] ; Remove our exception handle
  83. add esp, 8 ; clear stack
  84. pop esi
  85. pop edi
  86. pop ebx
  87. pop ebp
  88. stdRET _KiEm87StateToNpxFrame
  89. if DBG
  90. stnpx_err:
  91. stdCall _KeBugCheck <IRQL_NOT_LESS_OR_EQUAL>
  92. endif
  93. _KiEm87StateToNpxFrame ENDP
  94. stnpx_30 proc
  95. ;
  96. ; WARNING: Here we directly unlink the exception handler from the
  97. ; exception registration chain. NO unwind is performed. We can take
  98. ; this short cut because we know that our handler is a leaf-node.
  99. ;
  100. mov esp, [esp+8] ; (esp)-> ExceptionList
  101. xor eax, eax ; Return FALSE
  102. jmp short stnpx_10
  103. stnpx_30 endp
  104. ;*** SaveEnv
  105. ;
  106. ;
  107. ; ARGUMENTS
  108. ;
  109. ; (esi) = NpxFrame
  110. ; (ebx) = PcTeb
  111. ;
  112. ;
  113. ; DESCRIPTION
  114. ;
  115. SaveEnv:
  116. xor ax,ax
  117. mov [esi].reserved1,ax
  118. mov [esi].reserved2,ax
  119. mov [esi].reserved3,ax
  120. mov [esi].reserved4,ax
  121. mov [esi].reserved5,ax
  122. mov ax,[ebx].ControlWord
  123. mov [esi].E32_ControlWord,ax
  124. call GetEMSEGStatusWord
  125. mov [esi].E32_StatusWord,ax
  126. call GetTagWord
  127. mov [esi].E32_TagWord,ax
  128. mov ax,cs
  129. mov [esi].E32_CodeSeg,ax ; NOTE: Not R0 code & stack
  130. mov ax,ss
  131. mov [esi].E32_DataSeg,ax
  132. mov eax,[ebx].PrevCodeOff
  133. mov [esi].E32_CodeOff,eax
  134. mov eax,[ebx].PrevDataOff
  135. mov [esi].E32_DataOff,eax
  136. ret
  137. ;*** SaveState -
  138. ;
  139. ; ARGUMENTS
  140. ; (esi) = where to store environment
  141. ; (ebx) = PcTeb
  142. ;
  143. ; DESCRIPTION
  144. ;
  145. ; REGISTERS
  146. ; Destroys ALL, but EBX
  147. ;
  148. SaveState: ; Enter here for debugger save state
  149. mov dword ptr [esi].FpCr0NpxState, CR0_EM
  150. call SaveEnv
  151. add esi,size Env80x87_32 ;Skip over environment
  152. mov ebp,NumLev ;Save entire stack
  153. mov edi,[ebx].CURstk
  154. ss_loop:
  155. mov eax,[ebx+edi].ExpSgn
  156. call StoreTempReal ;in emstore.asm
  157. add esi,10
  158. mov edi,[ebx].CURstk
  159. ;;; NextStackElem edi,SaveState
  160. cmp edi,INITstk
  161. jae short ss_wrap
  162. add edi,Reg87Len
  163. ss_continue:
  164. mov [ebx].CURstk,edi
  165. dec ebp
  166. jnz short ss_loop
  167. ret
  168. ss_wrap:
  169. mov edi, BEGstk
  170. jmp short ss_continue
  171. ;*** GetTagWord - figures out what the tag word is from the numeric stack
  172. ; and returns the value of the tag word in ax.
  173. ;
  174. ; ARGUMENTS
  175. ; (ebx) = PcTeb
  176. ;
  177. GetTagWord:
  178. push esi
  179. xor eax, eax
  180. mov ecx, NumLev ; get tags for regs. 0, 7 - 1
  181. mov esi, INITstk
  182. GetTagLoop:
  183. mov dh, [ebx+esi].bTag ; The top 2 bits of Tag are the X87 tag bits.
  184. shld ax, dx, 2
  185. sub esi, Reg87Len
  186. loop GetTagLoop
  187. rol ax, 2 ; This moves Tag(0) into the low 2 bits
  188. pop esi
  189. ret
  190. ;*** GetEMSEGStatusWord
  191. ;
  192. ; User status word returned in ax.
  193. ; Uses status word in per-thread data area, otherwise
  194. ; identical to GetStatusWord
  195. ;
  196. ; ARGUMENTS
  197. ; (ebx) = PcTeb
  198. GetEMSEGStatusWord:
  199. mov eax, [ebx].CURstk
  200. sub eax, BEGstk
  201. ;
  202. ; Make sure the 'div' won't overflowed.
  203. ;
  204. cmp eax, Reg87Len * (NumLev + 2)
  205. ja short @f
  206. mov dl,Reg87Len
  207. div dl
  208. inc eax
  209. and eax, 7 ; eax is now the stack number
  210. shl ax, 11
  211. or ax, [ebx].StatusWord ; or in the rest of the status word.
  212. ret
  213. @@:
  214. mov eax, STATUS_INTEGER_OVERFLOW
  215. stdCall _ExRaiseStatus, <eax>
  216. ret ; Should never come here ...
  217. ;*** StoreTempReal
  218. ;
  219. ;
  220. ; ARGUMENTS
  221. ; ??
  222. ; (ebx) = PcTeb
  223. ;
  224. StoreTempReal:
  225. mov edx,[ebx+edi].lManHi
  226. mov edi,[ebx+edi].lManLo
  227. ;mantissa in edx:edi, exponent in high eax, sign in ah bit 7, tag in al
  228. ;memory destination is esi
  229. mov ecx,eax ;get copy of sign and tag
  230. shr ecx,16 ;Bring exponent down
  231. cmp al,bTAG_ZERO
  232. jz short StoreIEEE80 ;Skip bias if zero
  233. add ecx,IexpBias-TexpBias ;Correct bias
  234. cmp al,bTAG_DEN
  235. jz short Denorm80
  236. StoreIEEE80:
  237. and eax,bSign shl 8
  238. or ecx,eax ;Combine sign with exponent
  239. mov [esi],edi
  240. mov [esi+4],edx
  241. mov [esi+8],cx
  242. ret
  243. Denorm80:
  244. ;Must change it to a denormal
  245. dec ecx
  246. neg ecx ;Use as shift count
  247. cmp cl,32 ;Long shift?
  248. jae LongDenorm
  249. shrd edi,edx,cl
  250. shr edx,cl
  251. xor ecx,ecx ;Exponent is zero
  252. jmp short StoreIEEE80
  253. LongDenorm:
  254. ;edi must be zero if we have 32 bits to shift
  255. xchg edx,edi ;32-bit right shift
  256. shr edi,cl ;shift count is modulo-32
  257. xor ecx,ecx ;Exponent is zero
  258. jmp short StoreIEEE80
  259. ;****************************************************
  260. ;****************************************************
  261. ;****************************************************
  262. ;****************************************************
  263. ;*** _KiNpxFrameToEm87State
  264. ;
  265. ; Translates the NpxFrame to the R3 emulators state
  266. ;
  267. ; Returns TRUE if NpxFrame state sucessfully transfered.
  268. ; else FALSE
  269. ;
  270. ; Warning: This function can only be called at Irql 0 with interrupts
  271. ; enabled. It is intended to be called only to deal with R3 exceptions
  272. ; when the emulator is being used.
  273. ;
  274. ; Revision History:
  275. ;
  276. ;
  277. ;*******************************************************************************
  278. cPublicProc _KiNpxFrameToEm87State, 1
  279. push ebp
  280. mov ebp, esp
  281. push ebx ; Save C runtime varibles
  282. push edi
  283. push esi
  284. push esp ; Pass current Esp to handler
  285. push offset npxts_30 ; Set Handler address
  286. push PCR[PcExceptionList] ; Set next pointer
  287. mov PCR[PcExceptionList],esp ; Link us on
  288. if DBG
  289. pushfd ; Sanity check
  290. pop ecx ; make sure interrupts are enabled
  291. test ecx, EFLAGS_INTERRUPT_MASK
  292. jz short npxts_err
  293. CurrentIrql ; Sanity check
  294. cmp al, DISPATCH_LEVEL ; make sure Irql is below DPC level
  295. jnc short npxts_err
  296. endif
  297. xor eax, eax ; set FALSE
  298. mov ebx,PCR[PcPrcbData+PbCurrentThread]
  299. mov ebx,[ebx]+ThApcState+AsProcess
  300. cmp dword ptr [ebx]+PrVdmObjects,0 ; is this a vdm process?
  301. jne short npxts_10 ; Yes, then not supported
  302. mov ebx, PCR[PcTeb] ; R3 Teb
  303. cmp [ebx].Einstall, 0 ; Initialized?
  304. je short npxts_10 ; No, then don't set NpxFrame
  305. mov esi, [ebp+8] ; (esi) = NpxFrame
  306. call StorState
  307. or [ebx].CURErr, Summary ; Set completed
  308. mov eax, 1 ; Return TRUE
  309. npxts_10:
  310. pop PCR[PcExceptionList] ; Remove our exception handle
  311. add esp, 8 ; clear stack
  312. pop esi
  313. pop edi
  314. pop ebx
  315. pop ebp
  316. stdRet _KiNpxFrameToEm87State
  317. if DBG
  318. npxts_err:
  319. stdCall _KeBugCheck <IRQL_NOT_LESS_OR_EQUAL>
  320. endif
  321. _KiNpxFrameToEm87State ENDP
  322. npxts_30 proc
  323. ;
  324. ; WARNING: Here we directly unlink the exception handler from the
  325. ; exception registration chain. NO unwind is performed. We can take
  326. ; this short cut because we know that our handler is a leaf-node.
  327. ;
  328. mov esp, [esp+8] ; (esp)-> ExceptionList
  329. xor eax, eax ; Return FALSE
  330. jmp short npxts_10
  331. ret
  332. npxts_30 endp
  333. ;*** StorState - emulate FRSTOR [address]
  334. ;
  335. ; ARGUMENTS
  336. ; (esi) = where to get the environment
  337. ; (ebx) = PcTeb
  338. ;
  339. ;
  340. ; DESCRIPTION
  341. ; This routine emulates an 80387 FRSTOR (restore state)
  342. StorState:
  343. ;First we set up the status word so that [CURstk] is initialized.
  344. ;The floating-point registers are stored in logical ST(0) - ST(7) order,
  345. ;not physical register order. We don't do a full load of the environment
  346. ;because we're not ready to use the tag word yet.
  347. mov ax, [esi].E32_StatusWord
  348. call SetEmStatusWord ;Initialize [CURstk]
  349. add esi,size Env80x87_32 ;Skip over environment
  350. ;Load of temp real has one difference from real math chip: it is an invalid
  351. ;operation to load an unsupported format. By ensuring the exception is
  352. ;masked, we will convert unsupported format to Indefinite. Note that the
  353. ;mask and [CURerr] will be completely restored by the FLDENV at the end.
  354. mov [ebx].CWmask,3FH ;Mask off invalid operation exception
  355. mov edi,[ebx].CURstk
  356. mov ebp,NumLev
  357. FrstorLoadLoop:
  358. push esi
  359. call LoadTempReal ;In emload.asm
  360. pop esi
  361. add esi,10 ;Point to next temp real
  362. ;;; NextStackElem edi,Frstor
  363. cmp edi,INITstk
  364. jae short fr_wrap
  365. add edi,Reg87Len
  366. fr_continue:
  367. dec ebp
  368. jnz short FrstorLoadLoop
  369. sub esi,NumLev*10+size Env80x87_32 ;Point to start of env.
  370. ;
  371. ; Stor Enviroment
  372. ; (esi) = where to get enviroment
  373. ; (ebx) = PcTeb
  374. ;
  375. mov ax, [esi].E32_StatusWord
  376. call SetEmStatusWord ; set up status word
  377. mov ax, [esi].E32_ControlWord
  378. call SetControlWord
  379. mov ax, [esi].E32_TagWord
  380. call UseTagWord
  381. mov eax, [esi].E32_CodeOff
  382. mov [ebx].PrevCodeOff, eax
  383. mov eax, [esi].E32_DataOff
  384. mov [ebx].PrevDataOff, eax
  385. ret
  386. fr_wrap:
  387. mov edi, BEGstk
  388. jmp short fr_continue
  389. ;*** SetEmStatusWord -
  390. ;
  391. ; Given user status word in ax, set into emulator.
  392. ; Destroys ebx only.
  393. SetEmStatusWord:
  394. and ax,7F7FH
  395. mov cx,ax
  396. and cx,3FH ; set up CURerr in case user
  397. mov [ebx].CURerr,cl ; wants to force an exception
  398. mov ecx, eax
  399. and ecx, not (7 shl 11) ; remove stack field.
  400. mov [ebx].StatusWord, cx
  401. sub ah, 8 ; adjust for emulator's stack layout
  402. and ah, 7 shl 3
  403. mov al, ah
  404. shr ah, 1
  405. add al, ah ; stack field * 3 * 4
  406. .erre Reg87Len eq 12
  407. and eax, 255 ; eax is now 12*stack number
  408. add eax, BEGstk
  409. mov [ebx].CURstk, eax
  410. ret
  411. SetControlWord:
  412. and ax,0F3FH ; Limit to valid values
  413. mov [ebx].ControlWord, ax ; Store in the emulated control word
  414. not al ;Flip mask bits for fast compare
  415. and al,3FH ;Limit to valid mask bits
  416. mov [ebx].ErrMask,al
  417. and eax,(RoundControl + PrecisionControl) shl 8
  418. .erre RoundControl eq 1100B
  419. .erre PrecisionControl eq 0011B
  420. shr eax,6 ;Put PC and RC in bits 2-5
  421. mov ecx,_Ki387RoundModeTable
  422. mov ecx,[ecx+eax] ;Get correct RoundMode vector
  423. mov [ebx].RoundMode,ecx
  424. mov [ebx].SavedRoundMode,ecx
  425. and eax,RoundControl shl (8-6) ;Mask off precision control
  426. mov ecx,_Ki387RoundModeTable
  427. mov ecx,[ecx+(eax+PC64 shl (8-6))];Get correct RoundMode vector
  428. mov [ebx].TransRound,ecx ;Round mode w/o precision
  429. ret
  430. ;*** UseTagWord - Set up tags using tag word from environment
  431. ;
  432. ; ARGUMENTS
  433. ; ax - should contain the tag word
  434. ;
  435. ; Destroys ax,bx,cx,dx,di
  436. UseTagWord:
  437. ror ax, 2 ; mov Tag(0) into top bits of ax
  438. mov edi,INITstk
  439. mov ecx, NumLev
  440. UseTagLoop:
  441. mov dl,bTAG_EMPTY
  442. cmp ah, 0c0h ;Is register to be tagged Empty?
  443. jae short SetTag ;Yes, go mark it
  444. mov dl,[ebx+edi].bTag ;Get current tag
  445. cmp dl,bTAG_EMPTY ;Is register currently Empty?
  446. je short SetTagNotEmpty ;If so, go figure out tag for it
  447. SetTag:
  448. mov [ebx+edi].bTag,dl
  449. UseTagLoopCheck:
  450. sub edi, Reg87Len
  451. shl eax, 2
  452. loop UseTagLoop
  453. ret
  454. SetTagEmpty:
  455. mov [ebx+edi].bTag, bTAG_EMPTY
  456. jmp short UseTagLoopCheck
  457. SetTagNotEmpty:
  458. ;Register is currently tagged empty, but new tag word says it is not empty.
  459. ;Figure out a new tag for it. The rules are:
  460. ;
  461. ;1. Everything is either normalized or zero--unnormalized formats cannot
  462. ;get in. So if the high half mantissa is zero, the number is zero.
  463. ;
  464. ;2. Although the exponent bias is different, NANs and Infinities are in
  465. ;standard IEEE format - exponent is TexpMax, mantissa indicates NAN vs.
  466. ;infinity (mantissa for infinity is 800..000H).
  467. ;
  468. ;3. Denormals have an exponent less than TexpMin.
  469. ;
  470. ;4. If the low half of the mantissa is zero, it is tagged bTAG_SNGL
  471. ;
  472. ;5. Everything else is bTAG_VALID
  473. cmp [ebx+edi].lManHi, 0
  474. mov dl,bTAG_ZERO ;Try zero first
  475. jz short SetTag ;Is mantissa zero?
  476. mov edx,[ebx+edi].ExpSgn
  477. mov dl,bTAG_DEN
  478. cmp edx,TexpMin shl 16 ;Is it denormal?
  479. jl short SetTag
  480. cmp [ebx+edi].lManLo,0 ;Is low half zero?
  481. .erre bTAG_VALID eq 1
  482. .erre bTAG_SNGL eq 0
  483. setnz dl ;if low half==0 then dl=0 else dl=1
  484. cmp edx,TexpMax shl 16 ;Is it NAN or Infinity?
  485. jl short SetTag ;If not, it's valid
  486. .erre (bTAG_VALID - bTAG_SNGL) shl TAG_SHIFT eq (bTAG_NAN - bTAG_INF)
  487. shl dl,TAG_SHIFT
  488. add dl,bTAG_INF - bTAG_SNGL
  489. ;If the low bits were zero we have just changed bTAG_SNGL to bTAG_INF
  490. ;If the low bits weren't zero, we changed bTAG_VALID to bTAG_NAN
  491. ;See if infinity is really possible: is high half 80..00H?
  492. cmp [ebx+edi].lManHi,1 shl 31 ;Is it infinity?
  493. jz short SetTag ;Store tag for infinity or NAN
  494. mov dl,bTAG_NAN
  495. jmp short SetTag
  496. ;*** LoadTempReal
  497. ;
  498. ;
  499. ;
  500. LoadTempReal:
  501. mov ebx,[esi+4] ;Get high half of mantissa
  502. mov cx,[esi+8] ;Get exponent and sign
  503. mov esi,[esi] ;Get low half of mantissa
  504. mov eax,ecx
  505. and ch,7FH ;Mask off sign bit
  506. shl ecx,16 ;Move exponent to high end
  507. mov ch,ah ;Restore sign
  508. jz short ZeroOrDenorm80
  509. ;Check for unsupported format: unnormals (MSB not set)
  510. or ebx,ebx
  511. jns short Unsupported
  512. sub ecx,(IexpBias-TexpBias) shl 16 ;Correct the bias
  513. cmp ecx,TexpMax shl 16
  514. jge short NANorInf80
  515. SetupTag:
  516. or esi,esi ;Any bits in low half?
  517. .erre bTAG_VALID eq 1
  518. .erre bTAG_SNGL eq 0
  519. setnz cl ;if low half==0 then cl=0 else cl=1
  520. jmp short SaveStack
  521. NANorInf80:
  522. mov cl,bTAG_NAN
  523. cmp ebx,1 shl 31 ;Only 1 bit set means infinity
  524. jnz short SaveStack
  525. or esi,esi
  526. jnz short SaveStack
  527. mov cl,bTAG_INF
  528. jmp short SaveStack
  529. ZeroOrDenorm80:
  530. ;Exponent is zero. Number is either zero or denormalized
  531. or ebx,ebx
  532. jnz short ShortNorm80 ;Are top 32 bits zero?
  533. or esi,esi ;Are low 32 bits zero too?
  534. jnz LongNorm80
  535. mov cl,bTAG_ZERO
  536. jmp short SaveStack
  537. ;This code accepts and works correctly with pseudo-denormals (MSB already set)
  538. LongNorm80:
  539. xchg ebx,esi ;Shift up 32 bits
  540. sub ecx,32 shl 16 ;Correct exponent
  541. ShortNorm80:
  542. add ecx,(TexpBias-IexpBias+1-31) shl 16 ;Fix up bias
  543. bsr edx,ebx ;Scan for MSB
  544. ;Bit number in edx ranges from 0 to 31
  545. mov cl,dl
  546. not cl ;Convert bit number to shift count
  547. shld ebx,esi,cl
  548. shl esi,cl
  549. shl edx,16 ;Move exp. adjustment to high end
  550. add ecx,edx ;Adjust exponent
  551. jmp short SetUpTag
  552. SaveStack:
  553. mov eax, PCR[PcTeb]
  554. mov [eax].CURstk,edi
  555. mov [eax+edi].lManLo,esi
  556. mov [eax+edi].lManHi,ebx
  557. mov [eax+edi].ExpSgn,ecx
  558. mov ebx, eax ; (ebx) = PcTeb
  559. ret
  560. Unsupported:
  561. mov ebx, PCR[PcTeb]
  562. or [ebx].CURerr,Invalid ; (assume it's masked?)
  563. mov [ebx+edi].lManLo,0
  564. mov [ebx+edi].lManHi,0C0000000H
  565. mov [ebx+edi].ExpSgn,TexpMax shl 16 + bSign shl 8 + bTAG_NAN
  566. mov [ebx].CURstk,edi ;Update top of stack
  567. ret
  568. _TEXT ENDS
  569. END