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.

336 lines
6.5 KiB

  1. page ,132
  2. subttl emfixfly.asm - Fixup-on-the-fly routines
  3. ;***
  4. ;emfixfly.asm - Fixup-on-the-fly routines
  5. ;
  6. ; Copyright (c) 1987-89, Microsoft Corporation
  7. ;
  8. ;Purpose:
  9. ; Fixup-on-the-fly routines
  10. ;
  11. ; This Module contains Proprietary Information of Microsoft
  12. ; Corporation and should be treated as Confidential.
  13. ;
  14. ;Revision History:
  15. ; See emulator.hst
  16. ;
  17. ;*******************************************************************************
  18. ;*******************************************************************************
  19. ; 03/29/85 - added 286 optimizations to change FWAITs to NOPs
  20. ; 09/10/87 - added FWAIT's for BASIC error handling
  21. ; 11/02/87 - changed FWFixUpOnFly to check for errors
  22. ;*******************************************************************************
  23. ProfBegin FIXFLY
  24. ifdef DOS3
  25. pub SOFixUpOnFly
  26. sti ; turn on interrupts
  27. fwait ; For BASIC error handling
  28. push ax
  29. push bp
  30. push ds
  31. push si
  32. mov bp,sp ; Point to stack
  33. lds si,dword ptr 8[bp] ; Fetch ret address,(points to after instruction)
  34. mov al,[si] ; get ESC byte
  35. or byte ptr [si],0C0h ; turn back into ESC x byte
  36. dec si ; Make SI point to start off instruction
  37. dec si
  38. mov 8[bp],si ; Change ret address to return to instruction
  39. shr al,1 ; move 2 bits into correct position
  40. shr al,1
  41. shr al,1
  42. not al ; negate them
  43. and al,018h ; mask to middle 2 bits
  44. or al,fES ; turn into correct segmented override
  45. xchg al,ah ; into high half
  46. mov al,fFWAIT ; low byte
  47. mov [si],ax ; stuff it
  48. push bx
  49. mov bx,1 ; bx = 1 to skip segment override
  50. ifdef WF
  51. jmp fixupdone
  52. else
  53. jmp short fixupdone
  54. endif
  55. ; new routine - don't back patch - check for error
  56. ; UNDONE - need to change this for Windows - can't edit code
  57. ; need to check errorcode
  58. pub FWFixUpOnFly
  59. sti ; turn on interrupts
  60. fwait ; For BASIC error handling
  61. ifdef WF
  62. wfFaultHere = $-1
  63. ; int 3
  64. push ds ; ds[18] retip[20] retcs[22] retfl[24]
  65. push es ; es[16]
  66. pusha ;
  67. mov bp, sp ;
  68. mov ax, EMULATOR_DATA
  69. mov ds, ax
  70. cmp [wfGoFast], 1
  71. jnz WinSlow
  72. push [bp+22] ; faulting CS - get data alias
  73. push [wfSel]
  74. call ChangeSelector
  75. mov es, [wfSel]
  76. sub word ptr [bp+20], 2
  77. mov bx, [bp+20] ; point to faulting insn
  78. xor ax, ax
  79. xchg [wfInsn], ax
  80. or ax, ax ; are we here due to fault?
  81. je wfNoFault
  82. mov es:[bx], ax ; yes - restore 'fake' INT 3d
  83. xor ax,ax
  84. xchg [errorcode],al ; get and reset errorcode
  85. mov REMLSW, ax ; save error code
  86. popa
  87. pop es
  88. pop ds
  89. jmp WinFastContinue
  90. ; mov ax, 353eh
  91. ; int 21h
  92. ; mov ax, es ; does app have a handler?
  93. ; or ax, bx
  94. ; jz wfDone
  95. ;
  96. ; mov ax, [wfErr]
  97. ;
  98. ; push cs ; return to wfDone
  99. ; push offset wfDone
  100. ;
  101. ; push es ; call app handler
  102. ; push bx
  103. ;
  104. ; retf
  105. FWAITNOP equ (iNOP + 256*fFWAIT)
  106. wfNoFault: ; this was a 'real' INT 3d,
  107. mov es:[bx], FWAITNOP ; so we'll patch it to inline code
  108. wfDone:
  109. popa
  110. pop es
  111. pop ds
  112. iret
  113. WinSlow: ; can't use fast method, fall through
  114. popa
  115. pop es
  116. pop ds ; fall through into old code
  117. endif
  118. ifdef POLLING ; new exception handling under POLLING
  119. ifdef USE_IRET
  120. FWAITiret:
  121. iret ; Edit to nop if error occurs
  122. elseifdef WINDOWS
  123. push ds
  124. push ax
  125. mov ax, EMULATOR_DATA
  126. mov ds, ax
  127. cmp [ExceptFlag], 0 ; if not zero, 80x87 exception occured.
  128. pop ax
  129. pop ds
  130. jnz PolledException
  131. iret
  132. else ;DEFUALT
  133. FWAITRetF db bRETF ; Edit to 3 byte nop if error occurs
  134. FWAITRetF2 dw 2
  135. endif ;DEFAULT
  136. pub PolledException
  137. push eax ; same frame as in emerror.asm
  138. push ds ; get address from task DS
  139. ifdef standalone
  140. xor ax,ax
  141. mov ds,ax
  142. mov ds,ds:[4*TSKINT+2]
  143. elseifdef _COM_
  144. mov ds, [__EmDataSeg]
  145. else ;not standalone or _COM_
  146. mov ax,EMULATOR_DATA
  147. mov ds,ax
  148. endif ;not standalone or _COM_
  149. ;*
  150. ;* Reset fwait polling flag.
  151. ;*
  152. ifdef USE_IRET
  153. mov byte ptr cs:[FWAITiret], bIRET ; reset "iret"
  154. elseifdef WINDOWS
  155. mov [ExceptFlag], 0
  156. else ;DEFAULT
  157. mov [FWAITRetF], bRETF ; reset "retf 2"
  158. mov [FWAITRetF2], 2
  159. endif ;DEFAULT
  160. xor ax,ax
  161. xchg [errorcode],al ; get and reset errorcode
  162. ifdef WINDOWS
  163. mov REMLSW, ax ; save error code
  164. pop ds
  165. pop ax ; stack is now just an int stack frame
  166. WinFastContinue:
  167. inc bp
  168. push bp
  169. mov bp, sp
  170. push ds
  171. push ax ; save user's ax
  172. push cs ; must set up another stack frame
  173. mov ax, offset FF_DummyReturn
  174. push ax
  175. FF_DummyReturn:
  176. mov word ptr [bp-2], EMULATOR_DATA ; emulator's ds goes on first frame
  177. inc bp
  178. push bp
  179. mov bp, sp
  180. push ds ; push user's ds onto dummy stack frame
  181. mov ax, EMULATOR_DATA
  182. mov ds, ax
  183. push es ; if windows => setup SignalAddress for
  184. push bx ; far call
  185. mov ax, DOS_getvector*256 + TSKINT
  186. IntDOS
  187. mov word ptr [SignalAddress], bx
  188. mov word ptr [SignalAddress+2], es
  189. pop bx
  190. pop es
  191. mov ax, REMLSW ; al = error code
  192. call [SignalAddress] ; execute signal routine
  193. pop ds ; restore user's ds
  194. add sp, 6 ; get rid of dummy stack frame
  195. pop ax ; restore user's ax
  196. add sp, 2 ; get rid of emulator ds on stack
  197. pop bp
  198. dec bp
  199. iret ; return
  200. else ;not WINDOWS
  201. call [SignalAddress] ; execute signal routine
  202. pop ds ; restore user DS
  203. pop eax
  204. iret
  205. endif ;not WINDOWS
  206. else ;not POLLING
  207. push ax
  208. mov ax,FIWRQQ ; isolated FWAIT fixup
  209. jmp short FixUpOnFly
  210. endif ;not POLLING
  211. pub DSFixUpOnFly
  212. sti ; turn on interrupts
  213. fwait ; For BASIC error handling
  214. push ax
  215. mov ax,FIDRQQ ; DS segment fixup
  216. pub FixUpOnFly
  217. PUSH BP
  218. PUSH DS
  219. PUSH SI
  220. MOV BP,SP ; Point to stack
  221. LDS SI,dword ptr 8[BP] ; Fetch ret address,(points to after instruction)
  222. DEC SI ; Make SI point to instruction
  223. DEC SI
  224. MOV 8[BP],SI ; Change ret address to return to instruction
  225. SUB [SI],ax ; Remove Fixup to convert to 8087 instruction
  226. push bx
  227. xor bx,bx ; bx = 0 for no segment override
  228. ; For the 286 change FWAITs on numeric instructions to NOPs
  229. ;
  230. ; ds:si = FWAIT address
  231. ; ds:(si+bx+1) = 8087/287 instruction
  232. pub fixupdone
  233. push sp ; check for 286
  234. pop ax
  235. cmp ax,sp
  236. jne fixupxit ; not 286
  237. mov ax,[bx+si+1] ; get instruction
  238. and ax,030FBh ; mask for FSTCW/FSTSW/FSTENV/FSAVE
  239. cmp ax,030D9h ; underlying bits
  240. jne fixcheck2 ; not one of the above
  241. mov al,[bx+si+2] ; get 2nd byte of instruction again
  242. cmp al,0F0h ; check if kernel functions
  243. jb fixupxit ; no - exit
  244. pub fixcheck2
  245. mov ax,[bx+si+1] ; get instruction
  246. and ax,0FEFFh ; mask for FCLEX/FINIT
  247. cmp ax,0E2DBh ; underlying bits
  248. je fixupxit ; can't remove FWAIT
  249. mov ax,[bx+si+1] ; get instruction
  250. cmp ax,0E0DFh ; check for FSTSW AX
  251. je fixupxit ; can't remove FWAIT
  252. mov byte ptr [si],iNOP ; NOP the FWAIT
  253. pub fixupxit
  254. pop bx
  255. POP SI
  256. POP DS
  257. POP BP
  258. pop ax
  259. IRET
  260. endif ;DOS3
  261. ProfEnd FIXFLY