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.

399 lines
8.0 KiB

  1. page ,132
  2. subttl emerror.asm - Emulator error handler
  3. ;***
  4. ;emerror.asm - Emulator error handler
  5. ;
  6. ; Copyright (c) 1987-89, Microsoft Corporation
  7. ;
  8. ;Purpose:
  9. ; Emulator error handler
  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. ProfBegin ERROR
  19. ; error entry to check for unmasked errors
  20. error_return macro noerror
  21. pop eax ; common exit code
  22. ifdef XENIX
  23. ifdef i386
  24. pop ss ; pop stack selector
  25. endif
  26. ifnb <noerror>
  27. iretd ; normal return
  28. else
  29. int 0FFh ; special XENIX int for error
  30. endif
  31. else
  32. iretd
  33. endif ;XENIX
  34. endm
  35. TESTif macro nam
  36. mov bl,err&nam ; default error number
  37. IF (nam GE 100H)
  38. test ah,nam/256
  39. ELSE ;not (nam GE 100H)
  40. test al,nam
  41. ENDIF ;(nam GE 100H)
  42. jnz short signalerror
  43. endm
  44. pub CommonExceptions
  45. ifdef QB3
  46. jmp $EM_INT ; jump to QB3 error handler
  47. else ;not QB3
  48. push ds ; get address from task DS
  49. push ebx
  50. TESTif StackUnderflow ; Stack underflow
  51. TESTif StackOverflow ; Stack overflow
  52. TESTif SquareRootNeg ; Square root of negative number?
  53. TESTif IntegerOverflow ; Would number not fit in integer?
  54. TESTif Invalid ; indefinite error ?
  55. TESTif ZeroDivide ; zero divide error ?
  56. TESTif Overflow ; overflow error ?
  57. TESTif Underflow ; underflow error ?
  58. ; TESTif Denormal ; denormal error ? not yet implemented
  59. TESTif Precision ; Precision error ?
  60. TESTif Unemulated ; unemulated error ?
  61. ; BL = error code value
  62. pub signalerror
  63. ifndef XENIX
  64. ifdef MTHREAD
  65. LOADthreadDS ; macro in emthread.asm
  66. ; load thread's DS; trash AX
  67. elseifdef standalone
  68. xor ax,ax
  69. mov ds,ax
  70. mov ds,ds:[4*TSKINT+2]
  71. elseifdef _COM_
  72. mov ds, [__EmDataSeg]
  73. else ;Default
  74. mov ax, edataBASE
  75. mov ds,ax
  76. endif ;Default
  77. ifdef MTHREAD
  78. ; lock _SIGNAL_LOCK to guard SignalAddress (also used by signal func.)
  79. mov ax,DGROUP
  80. mov ds,ax ; establish DS == DGROUP for __lock
  81. push _SIGNAL_LOCK
  82. call __lockf
  83. add sp,2
  84. mov ax,EMULATOR_DATA ; use thread 1's data segment
  85. mov ds,ax ; establish DS == EMULATOR_DATA
  86. mov ax,word ptr [SignalAddress] ; check for nonzero address
  87. or ax,word ptr [SignalAddress+2]
  88. jnz short havehandler
  89. ; go straight to DOSEXIT call below ...
  90. ; don't bother cleaning up the stack or unlocking _SIGNAL_LOCK
  91. ;pop bx ; don't bother tossing
  92. ;pop ebx ; don't bother tossing
  93. ;pop ds ; don't bother tossing
  94. mov ax,1
  95. push ax
  96. ; BL = error code value
  97. xchg ax,bx ; al = return code
  98. xor ah,ah
  99. push ax
  100. os2call DOSEXIT ; DOSEXIT(1,return code) to terminate process
  101. elseifdef WINDOWS
  102. push es
  103. push bx
  104. mov ax, DOS_getvector*256 + TSKINT
  105. IntDOS
  106. mov ax, es
  107. or ax, bx
  108. pop bx
  109. pop es
  110. jnz short havehandler
  111. else ;not MTHREAD or WINDOWS
  112. mov ax,word ptr [SignalAddress]
  113. or ax,word ptr [SignalAddress+2]
  114. jnz short havehandler
  115. ; UNDONE - why no "os2call DOSEXIT" for the DOS5 case?
  116. ;pop bx ; don't bother tossing
  117. ;pop ds ; don't bother tossing
  118. xchg ax,bx ; al = return code
  119. mov ah,04Ch
  120. int 21h ; terminate process with fp error code
  121. endif ;not MTHREAD or WINDOWS
  122. pub havehandler
  123. ifdef MTHREAD
  124. ; DS == EMULATOR_DATA ; Use thread 1's DS for SignalAddress.
  125. ; BL = return code
  126. xchg ax,bx ; al = return code
  127. push word ptr [SignalAddress+2]
  128. push word ptr [SignalAddress]
  129. mov bx,DGROUP
  130. mov ds,bx ; establish DS == DGROUP for __unlock
  131. push _SIGNAL_LOCK ; unlock _SIGNAL_LOCK
  132. call __unlockf
  133. add sp,2
  134. mov bx,sp ; SS:BX points to a copy of SignalAddress on the stack
  135. else ;not MTHREAD
  136. ; bl = return code
  137. xchg ax,bx ; al = return code
  138. ; other error return info for recovery
  139. pop ebx
  140. endif ;not MTHREAD
  141. ; all registers are the original values except AX and DS
  142. ;
  143. ; al = error code (81h and up)
  144. ;
  145. ; if the signal routine is going to return to the user program, it can
  146. ; just do a long ret. The users DS is sitting above the far return address
  147. ifdef POLLING ; new exception handling code
  148. ifndef frontend
  149. ifdef DOS3and5
  150. cmp [protmode],0 ; check for protect mode
  151. jne callsig ; yes - call signal now
  152. endif ;DOS3and5
  153. ifdef DOS3
  154. cmp [have8087],0 ; check if emulating
  155. je callsig ; yes - call signal now
  156. cmp [errorcode],0 ; check if pending error
  157. ifdef WF
  158. je ncs1
  159. jmp nocallsig
  160. ncs1:
  161. else
  162. jne nocallsig ; yes - just return
  163. endif
  164. mov [errorcode],al ; save error code for later
  165. ;*
  166. ;* Set 80x87 exception occured flag.
  167. ;*
  168. ifdef USE_IRET
  169. mov byte ptr cs:[FWAITiret], iNOP ; nop out "iret"
  170. elseifdef WINDOWS
  171. ifdef WF
  172. cmp [wfGoFast], 0
  173. je WinSlow2
  174. .286p
  175. ; int 3
  176. push bp ; bp[0], ds[2], ax[4], retip[6], retcs[8], retfl[10]
  177. mov bp, sp ; faultip[12], faultcs[14]
  178. push es
  179. pusha
  180. mov ax, REMLSW
  181. mov [wfErr], ax
  182. push cs ; if fault CS:IP == our int 3d handler
  183. pop ax ; then we don't want to patch it, we just want
  184. cmp [bp+14], ax ; to set the flag as if we had
  185. jnz wfPatch
  186. mov ax, offset wfFaultHere
  187. cmp [bp+12], ax
  188. jnz wfPatch
  189. mov [wfInsn], 3dcdh
  190. jmp short wfNoPatch
  191. wfPatch:
  192. push [bp+14] ; copy faulting CS to data selector
  193. push [wfSel]
  194. call ChangeSelector
  195. mov es, [wfSel] ; es:bx points to faulting insn
  196. mov bx, [bp+12]
  197. mov ax, es:[bx] ; save old insn value
  198. mov [wfInsn], ax
  199. mov es:[bx], 3dcdh ; put INT 3D at fault location
  200. wfNoPatch:
  201. popa
  202. pop es
  203. pop bp
  204. pop ds
  205. pop ax
  206. iret
  207. ; fall through to old code
  208. WinSlow2:
  209. endif
  210. mov [ExceptFlag], 1
  211. else ;DEFAULT
  212. mov byte ptr cs:[FWAITRetF], iNOP ; nop out "retf 2"
  213. mov word ptr cs:[FWAITRetF2], wNOP
  214. endif ;DEFAULT
  215. jmp short nocallsig ; just return
  216. endif ;DOS3
  217. endif ;not frontend
  218. endif ;POLLING
  219. callsig:
  220. ifdef MTHREAD
  221. call dword ptr ss:[bx] ; call thru thread 1's signal address
  222. add sp, 4 ; remove address of signal handler from stack
  223. pop ebx ; note that bx is restored after the call to the
  224. ; SIGFPE signal handler, but the SIG_DFL, SIG_IGN, or
  225. ; user-handler shouldn't care; in the event of SIG_IGN
  226. ; or a user handler that actually returns instead of
  227. ; doing longjump(), this pop instruction will restore bx
  228. elseifdef WINDOWS
  229. mov REMLSW, ax ; save error code
  230. pop ds
  231. pop ax ; stack is now just an int stack frame
  232. ifdef WF0
  233. .286p
  234. ; int 3
  235. push bp ; bp[0], retip[2], retcs[4], retfl[6]
  236. mov bp, sp ; faultip[8], faultcs[10]
  237. push ds
  238. push es
  239. pusha
  240. mov ax, EMULATOR_DATA
  241. mov ds, ax
  242. cmp [wfGoFast], 1 ; if running Std Mode
  243. jnz WinSlow2
  244. mov ax, REMLSW
  245. mov [wfErr], ax
  246. push [bp+10] ; copy faulting CS to data selector
  247. push [wfSel]
  248. call ChangeSelector
  249. mov es, [wfSel] ; es:bx points to faulting insn
  250. mov bx, [bp+8]
  251. mov ax, es:[bx] ; save old insn value
  252. mov [wfInsn], ax
  253. mov es:[bx], 3dcdh ; put INT 3D at fault location
  254. popa
  255. pop es
  256. pop ds
  257. pop bp
  258. iret
  259. WinSlow2: ; can't do fast (non-poll) fp, so
  260. popa ; restore stack and use old method
  261. pop es
  262. pop ds
  263. pop bp
  264. ; fall through to old code
  265. endif
  266. inc bp
  267. push bp
  268. mov bp, sp
  269. push ds
  270. push ax ; save user's ax
  271. push cs ; must set up another stack frame
  272. mov ax, offset DummyReturn
  273. push ax
  274. DummyReturn:
  275. mov word ptr [bp-2], EMULATOR_DATA ; emulator's ds goes on first frame
  276. inc bp
  277. push bp
  278. mov bp, sp
  279. push ds ; push user's ds onto dummy stack frame
  280. mov ax, EMULATOR_DATA
  281. mov ds, ax
  282. push es ; if windows => setup SignalAddress for
  283. push bx ; far call
  284. mov ax, DOS_getvector*256 + TSKINT
  285. IntDOS
  286. mov word ptr [SignalAddress], bx
  287. mov word ptr [SignalAddress+2], es
  288. pop bx
  289. pop es
  290. mov ax, REMLSW ; al = error code
  291. call [SignalAddress] ; execute signal routine
  292. pop ds ; restore user's ds
  293. add sp, 6 ; get rid of dummy stack frame
  294. pop ax ; restore user's ax
  295. add sp, 2 ; get rid of emulator ds on stack
  296. pop bp
  297. dec bp
  298. iret ; return
  299. else ;not MTHREAD or WINDOWS
  300. call [SignalAddress] ; execute signal routine
  301. endif ;not MTHREAD or WINDOWS
  302. nocallsig:
  303. pop ds ; restore user DS
  304. error_return noerror ; treat as if nothing happened
  305. else ;XENIX
  306. pop ebx ; restore EBX and DS
  307. pop ds
  308. error_return ; error exit for XENIX
  309. endif ;XENIX
  310. endif ;not QB3
  311. ProfEnd ERROR