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.

798 lines
21 KiB

  1. // TITLE("Miscellaneous Exception Handling")
  2. //++
  3. //
  4. // Module Name:
  5. //
  6. // xcptmisc.s
  7. //
  8. // Abstract:
  9. //
  10. // This module implements miscellaneous routines that are required to
  11. // support exception handling. Functions are provided to call an exception
  12. // handler for an exception, call an exception handler for unwinding, call
  13. // an exception filter, and call a termination handler.
  14. //
  15. // Author:
  16. //
  17. // William K. Cheung (wcheung) 15-Jan-1996
  18. //
  19. // based on the version by David N. Cutler (davec) 12-Sep-1990
  20. //
  21. // Environment:
  22. //
  23. // Any mode.
  24. //
  25. // Revision History:
  26. //
  27. // Updated to EAS2.1
  28. //
  29. //--
  30. #include "ksia64.h"
  31. .file "xcptmisc.s"
  32. //++
  33. //
  34. // EXCEPTION_DISPOSITION
  35. // RtlpExceptionHandler (
  36. // IN PEXCEPTION_RECORD ExceptionRecord,
  37. // IN FRAME_POINTERS EstablisherFrame,
  38. // IN OUT PCONTEXT ContextRecord,
  39. // IN OUT PDISPATCHER_CONTEXT DispatcherContext
  40. // )
  41. //
  42. // Routine Description:
  43. //
  44. // This function is called when a nested exception occurs. Its function
  45. // is to retrieve the establisher frame pointer from its establisher's
  46. // call frame, store this information in the dispatcher context record,
  47. // and return a disposition value of nested exception.
  48. //
  49. // Arguments:
  50. //
  51. // ExceptionRecord (a0) - Supplies a pointer to an exception record.
  52. //
  53. // EstablisherFrame (a1,a2) - Supplies the memory stack and backing store
  54. // frame pointers of the establisher of this exception handler.
  55. //
  56. // ContextRecord (a3) - Supplies a pointer to a context record.
  57. //
  58. // DispatcherContext (a4) - Supplies a pointer to the dispatcher context
  59. // record.
  60. //
  61. // Return Value:
  62. //
  63. // A disposition value ExceptionNestedException is returned if an unwind
  64. // is not in progress. Otherwise a value of ExceptionContinueSearch is
  65. // returned.
  66. //
  67. //--
  68. LEAF_ENTRY(RtlpExceptionHandler)
  69. //
  70. // register aliases
  71. //
  72. pUwnd = pt0
  73. pNot = pt1
  74. //
  75. // Check if unwind is in progress.
  76. //
  77. add t0 = ErExceptionFlags, a0
  78. ;;
  79. ld4.nt1 t0 = [t0]
  80. mov t1 = EXCEPTION_UNWIND
  81. ;;
  82. add t3 = -8, a1
  83. and t0 = t0, t1
  84. add t2 = DcEstablisherFrame, a4
  85. ;;
  86. ld8.nt1 t4 = [t3] // get dispatcher context addr
  87. cmp4.ne pUwnd, pNot = zero, t0 // if ne, unwind in progress
  88. ;;
  89. (pNot) add t5 = DcEstablisherFrame, t4
  90. ;;
  91. //
  92. // If unwind is not in progress - return nested exception disposition.
  93. // And copy the establisher frame pointer structure (i.e. FRAME_POINTERS)
  94. // to the current dispatcher context.
  95. //
  96. // Otherwise, return continue search disposition
  97. //
  98. (pNot) ld8.nt1 t6 = [t5], 8
  99. (pNot) mov v0 = ExceptionNestedException // set disposition value
  100. (pUwnd) mov v0 = ExceptionContinueSearch // set disposition value
  101. ;;
  102. (pNot) ld8.nt1 t7 = [t5]
  103. (pNot) st8 [t2] = t6, 8
  104. nop.i 0
  105. ;;
  106. (pNot) st8 [t2] = t7
  107. nop.m 0
  108. br.ret.sptk.clr brp
  109. ;;
  110. LEAF_EXIT(RtlpExceptionHandler)
  111. //++
  112. //
  113. // EXCEPTION_DISPOSITION
  114. // RtlpExecuteEmHandlerForException (
  115. // IN PEXCEPTION_RECORD ExceptionRecord,
  116. // IN ULONGLONG MemoryStack,
  117. // IN ULONGLONG BackingStore,
  118. // IN OUT PCONTEXT ContextRecord,
  119. // IN OUT PDISPATCHER_CONTEXT DispatcherContext,
  120. // IN ULONGLONG GlobalPointer,
  121. // IN PEXCEPTION_ROUTINE ExceptionRoutine
  122. // )
  123. //
  124. // Routine Description:
  125. //
  126. // This function stores the establisher's dispatcher context in the stack
  127. // scratch area, establishes an exception handler, and then calls
  128. // the specified exception handler as an exception handler. If a nested
  129. // exception occurs, then the exception handler of this function is called
  130. // and the establisher frame pointer in the saved dispatcher context
  131. // is returned to the exception dispatcher via the dispatcher context
  132. // parameter of this function's exception handler. If control is returned
  133. // to this routine, then the disposition status is returned to the
  134. // exception dispatcher.
  135. //
  136. // Arguments:
  137. //
  138. // ExceptionRecord (a0) - Supplies a pointer to an exception record.
  139. //
  140. // MemoryStack (a1) - Supplies the memory stack frame pointer of the
  141. // activation record whose exception handler is to be called.
  142. //
  143. // BackingStore (a2) - Supplies the backing store pointer of the
  144. // activation record whose exception handler is to be called.
  145. //
  146. // ContextRecord (a3) - Supplies a pointer to a context record.
  147. //
  148. // DispatcherContext (a4) - Supplies a pointer to the dispatcher context
  149. // record.
  150. //
  151. // GlobalPointer (a5) - Supplies the global pointer value of the module
  152. // to which the function belongs.
  153. //
  154. // ExceptionRoutine (a6) - supplies a pointer to the exception handler
  155. // that is to be called.
  156. //
  157. // Return Value:
  158. //
  159. // The disposition value returned by the specified exception handler is
  160. // returned as the function value.
  161. //
  162. //--
  163. NESTED_ENTRY_EX(RtlpExecuteEmHandlerForException,RtlpExceptionHandler)
  164. //
  165. // register aliases
  166. //
  167. rpT0 = t8
  168. rpT1 = t9
  169. .prologue
  170. .fframe 32, tg30
  171. alloc t1 = ar.pfs, 0, 0, 7, 0
  172. mov t0 = brp
  173. mov rpT0 = sp
  174. add rpT1 = 8, sp
  175. [tg30:] add sp = -32, sp
  176. ;;
  177. .savesp rp, 32
  178. st8 [rpT0] = t0, -8 // save brp
  179. .savesp ar.pfs, 32+8
  180. st8 [rpT1] = t1, 8 // save pfs
  181. ;;
  182. PROLOGUE_END
  183. //
  184. // Setup global pointer and branch register for the except handler
  185. //
  186. ld8 t2 = [a6], PlGlobalPointer - PlEntryPoint
  187. st8.nta [rpT0] = a4 // save dispatcher context addr
  188. ;;
  189. ld8 gp = [a6]
  190. mov bt0 = t2
  191. br.call.sptk.many brp = bt0 // call except handler
  192. //
  193. // Save swizzled dispatcher context address onto the stack
  194. //
  195. .restore tg40
  196. [tg40:] add sp = 32, sp // deallocate stack frame
  197. ;;
  198. ld8.nt1 t0 = [sp]
  199. add rpT1 = 8, sp
  200. ;;
  201. ld8.nt1 t1 = [rpT1]
  202. nop.f 0
  203. mov brp = t0 // restore return branch
  204. ;;
  205. nop.m 0
  206. mov ar.pfs = t1 // restore pfs
  207. br.ret.sptk.clr brp // return
  208. NESTED_EXIT(RtlpExecuteEmHandlerForException)
  209. //++
  210. //
  211. // EXCEPTION_DISPOSITION
  212. // RtlpEmUnwindHandler (
  213. // IN PEXCEPTION_RECORD ExceptionRecord,
  214. // IN FRAME_POINTERS EstablisherFrame,
  215. // IN OUT PCONTEXT ContextRecord,
  216. // IN OUT PVOID DispatcherContext
  217. // )
  218. //
  219. // Routine Description:
  220. //
  221. // This function is called when a collided unwind occurs. Its function
  222. // is to retrieve the establisher dispatcher context, copy it to the
  223. // current dispatcher context, and return a disposition value of nested
  224. // unwind.
  225. //
  226. // Arguments:
  227. //
  228. // ExceptionRecord (a0) - Supplies a pointer to an exception record.
  229. //
  230. // EstablisherFrame (a1,a2) - Supplies the memory stack and backing store
  231. // frame pointers of the establisher of this exception handler.
  232. //
  233. // ContextRecord (a3) - Supplies a pointer to a context record.
  234. //
  235. // DispatcherContext (a4) - Supplies a pointer to the dispatcher context
  236. // record.
  237. //
  238. // Return Value:
  239. //
  240. // A disposition value ExceptionCollidedUnwind is returned if an unwind is
  241. // in progress. Otherwise, a value of ExceptionContinueSearch is returned.
  242. //
  243. //--
  244. LEAF_ENTRY(RtlpEmUnwindHandler)
  245. //
  246. // register aliases
  247. //
  248. #if 0
  249. pUwnd = pt0
  250. pNot = pt1
  251. //
  252. // Check if unwind is in progress.
  253. //
  254. add t0 = ErExceptionFlags, a0
  255. ;;
  256. ld4.nt1 t0 = [t0]
  257. mov t1 = EXCEPTION_UNWIND
  258. ;;
  259. and t0 = t0, t1
  260. ;;
  261. cmp4.eq pNot, pUwnd = zero, t0 // if eq, unwind not in progress
  262. (pNot) br.cond.sptk Ruh10
  263. #endif // 0
  264. add t2 = -8, a1
  265. add t1 = 8, a4 // -> target dispatch context+8
  266. ;;
  267. ld8.nt1 t2 = [t2] // -> source dispatch context
  268. ;;
  269. add t3 = 8, t2 // -> source dispatch context+8
  270. nop.i 0
  271. ;;
  272. //
  273. // Copy the establisher dispatcher context (i.e. DISPATCHER_CONTEXT) contents
  274. // to the current dispatcher context.
  275. //
  276. ld8 t6 = [t2], 16
  277. ld8 t7 = [t3], 16
  278. nop.i 0
  279. ;;
  280. ld8 t8 = [t2], 16
  281. ld8 t9 = [t3], 16
  282. nop.i 0
  283. ;;
  284. st8 [a4] = t6, 16
  285. st8 [t1] = t7, 16
  286. nop.i 0
  287. LDPTR (t10, t2)
  288. LDPTR (t11, t3)
  289. nop.i 0
  290. ;;
  291. st8 [a4] = t8, 16
  292. st8 [t1] = t9, 16
  293. mov v0 = ExceptionCollidedUnwind // set disposition value
  294. ;;
  295. STPTR (a4, t10)
  296. STPTR (t1, t11)
  297. br.ret.sptk.clr brp // return
  298. ;;
  299. #if 0
  300. Ruh10:
  301. //
  302. // If branched to here,
  303. // unwind is not in progress - return continue search disposition.
  304. //
  305. nop.m 0
  306. (pNot) mov v0 = ExceptionContinueSearch // set disposition value
  307. br.ret.sptk.clr brp // return
  308. #endif // 0
  309. LEAF_EXIT(RtlpEmUnwindHandler)
  310. //++
  311. //
  312. // EXCEPTION_DISPOSITION
  313. // RtlpExecuteEmHandlerForUnwind (
  314. // IN PEXCEPTION_RECORD ExceptionRecord,
  315. // IN ULONGLONG MemoryStack,
  316. // IN ULONGLONG BackingStore,
  317. // IN OUT PCONTEXT ContextRecord,
  318. // IN OUT PVOID DispatcherContext,
  319. // IN ULONGLONG GlobalPointer,
  320. // IN PEXCEPTION_ROUTINE ExceptionRoutine
  321. // )
  322. //
  323. // Routine Description:
  324. //
  325. // This function allocates a call frame, stores the establisher frame
  326. // pointer and the context record address in the frame, establishes an
  327. // exception handler, and then calls the specified exception handler as
  328. // an unwind handler. If a collided unwind occurs, then the exception
  329. // handler of of this function is called and the establisher frame pointer
  330. // and context record address are returned to the unwind dispatcher via
  331. // the dispatcher context parameter. If control is returned to this routine,
  332. // then the frame is deallocated and the disposition status is returned to
  333. // the unwind dispatcher.
  334. //
  335. // Arguments:
  336. //
  337. // ExceptionRecord (a0) - Supplies a pointer to an exception record.
  338. //
  339. // MemoryStack (a1) - Supplies the memory stack frame pointer of the
  340. // activation record whose exception handler is to be called.
  341. //
  342. // BackingStore (a2) - Supplies the backing store pointer of the
  343. // activation record whose exception handler is to be called.
  344. //
  345. // ContextRecord (a3) - Supplies a pointer to a context record.
  346. //
  347. // DispatcherContext (a4) - Supplies a pointer to the dispatcher context
  348. // record.
  349. //
  350. // GlobalPointer (a5) - Supplies the global pointer value of the module
  351. // to which the function belongs.
  352. //
  353. // ExceptionRoutine (a6) - supplies a pointer to the exception handler
  354. // that is to be called.
  355. //
  356. // Return Value:
  357. //
  358. // The disposition value returned by the specified exception handler is
  359. // returned as the function value.
  360. //
  361. //--
  362. NESTED_ENTRY_EX(RtlpExecuteEmHandlerForUnwind, RtlpEmUnwindHandler)
  363. //
  364. // register aliases
  365. //
  366. .prologue
  367. .fframe 32, tg10
  368. rpT0 = t8
  369. rpT1 = t9
  370. alloc t1 = ar.pfs, 0, 0, 7, 0
  371. mov t0 = brp
  372. mov rpT0 = sp
  373. add rpT1 = 8, sp
  374. [tg10:] add sp = -32, sp
  375. ;;
  376. .savepsp rp, 0
  377. st8 [rpT0] = t0, -8 // save brp
  378. .savepsp ar.pfs, -8
  379. st8 [rpT1] = t1, 8 // save pfs
  380. ;;
  381. PROLOGUE_END
  382. //
  383. // Setup global pointer and branch register for the except handler
  384. //
  385. ld8 t2 = [a6], PlGlobalPointer - PlEntryPoint
  386. st8.nta [rpT0] = a4 // save dispatcher context addr
  387. ;;
  388. ld8 gp = [a6]
  389. mov bt0 = t2
  390. (p0) br.call.sptk.many brp = bt0 // call except handler
  391. //
  392. // Save swizzled dispatcher context address onto the stack
  393. //
  394. .restore tg20
  395. [tg20:] add sp = 32, sp // deallocate stack frame
  396. ;;
  397. ld8.nt1 t0 = [sp]
  398. add rpT1 = 8, sp
  399. ;;
  400. ld8.nt1 t1 = [rpT1]
  401. nop.f 0
  402. mov brp = t0 // restore return branch
  403. ;;
  404. nop.m 0
  405. mov ar.pfs = t1 // restore pfs
  406. br.ret.sptk.clr brp // return
  407. ;;
  408. NESTED_EXIT(RtlpExecuteEmHandlerForUnwind)
  409. #if 0
  410. //++
  411. //
  412. // EXCEPTION_DISPOSITION
  413. // RtlpUnwindHandler (
  414. // IN PEXCEPTION_RECORD ExceptionRecord,
  415. // IN FRAME_POINTERS EstablisherFrame,
  416. // IN OUT PCONTEXT ContextRecord,
  417. // IN OUT PVOID DispatcherContext
  418. // )
  419. //
  420. // Routine Description:
  421. //
  422. // This function is called when a collided unwind occurs. Its function
  423. // is to retrieve the establisher dispatcher context, copy it to the
  424. // current dispatcher context, and return a disposition value of nested
  425. // unwind.
  426. //
  427. // Arguments:
  428. //
  429. // ExceptionRecord (a0) - Supplies a pointer to an exception record.
  430. //
  431. // EstablisherFrame (a1,a2) - Supplies the memory stack and backing store
  432. // frame pointers of the establisher of this exception handler.
  433. //
  434. // ContextRecord (a3) - Supplies a pointer to a context record.
  435. //
  436. // DispatcherContext (a4) - Supplies a pointer to the dispatcher context
  437. // record.
  438. //
  439. // Return Value:
  440. //
  441. // A disposition value ExceptionCollidedUnwind is returned if an unwind is
  442. // in progress. Otherwise, a value of ExceptionContinueSearch is returned.
  443. //
  444. //--
  445. LEAF_ENTRY(RtlpUnwindHandler)
  446. LEAF_RETURN
  447. LEAF_EXIT(RtlpUnwindHandler)
  448. //
  449. // constants & register aliases for EM-iA transition stubs
  450. //
  451. rIA32Ptr = r2 // IA32 resources pointer
  452. rTeb = r3 // TEB pointer
  453. rIA32Rsrc = ar.k7 // Offset in TEB for iA32 stuff
  454. rES = r16
  455. rCS = r17
  456. rSS = r18
  457. rDS = r19
  458. rFS = r20
  459. rGS = r21
  460. rLDT = r22
  461. rEFLAG = ar24
  462. rESD = r24
  463. rCSD = ar25
  464. rSSD = ar26
  465. rDSD = r27
  466. rFSD = r28
  467. rGSD = r29
  468. rLDTD = r30
  469. rGDTD = r31
  470. isIA = pt0
  471. isTIA = pt1
  472. //++
  473. //
  474. // EXCEPTION_DISPOSITION
  475. // RtlpExecuteX86HandlerForException (
  476. // IN PEXCEPTION_RECORD ExceptionRecord,
  477. // IN PVOID EstablisherFrame,
  478. // IN OUT PCONTEXT ContextRecord,
  479. // IN OUT PDISPATCHER_CONTEXT DispatcherContext,
  480. // IN PEXCEPTION_ROUTINE ExceptionRoutine
  481. // )
  482. //
  483. // Arguments:
  484. //
  485. // ExceptionRecord (a0) - Supplies a pointer to an exception record.
  486. //
  487. // EstablisherFrame (a1) - Supplies the frame pointer of the establisher
  488. // whose exception handler is to be called.
  489. //
  490. // ContextRecord (a2) - Supplies a pointer to a context record.
  491. //
  492. // DispatcherContext (a3) - Supplies a pointer to the dispatcher context
  493. // record.
  494. //
  495. // ExceptionRoutine (a4) - supplies a pointer to the exception handler
  496. // that is to be called.
  497. //
  498. // Return Value:
  499. //
  500. // The disposition value returned by the specified exception handler is
  501. // returned as the function value.
  502. //
  503. //--
  504. NESTED_ENTRY_EX(RtlpExecuteX86HandlerForException,RtlpExceptionHandler)
  505. .regstk 5, 6, 0, 0
  506. .prologue 0xe, loc0
  507. alloc loc1 = ar.pfs, 5, 6, 0, 0
  508. mov loc2 = brp
  509. mov loc0 = sp
  510. PROLOGUE_END
  511. mov rTeb = teb
  512. add r13 = 4, sp
  513. mov r14 = sp
  514. mov loc3 = ar.fpsr
  515. sxt4 a3 = a3
  516. sxt4 gp = a4
  517. ;;
  518. mov rIA32Ptr = rIA32Rsrc
  519. st4 [r14] = a0, 8
  520. mov loc4 = pr
  521. ;;
  522. st4 [r13] = a1, 8
  523. st4 [r14] = a2, 16
  524. mov loc5 = ar.lc
  525. ;;
  526. st4 [r13] = a3
  527. mov bt0 = gp
  528. br.call.sptk brp = _EM_IA_ExecuteHandler_Transition
  529. mov ar.fpsr = loc3
  530. mov ar.pfs = loc0
  531. mov brp = loc1
  532. add sp = r0, loc2
  533. mov pr = loc4, -1
  534. mov ar.lc = loc5
  535. nop.m 0
  536. nop.m 0
  537. br.ret.sptk.clr brp
  538. NESTED_EXIT(RtlpExecuteX86HandlerForException)
  539. LEAF_ENTRY(_EM_IA_ExecuteHandler_Transition)
  540. alloc loc1 = ar.pfs, 0, 96, 0, 0
  541. add rIA32Ptr = rIA32Ptr, rTeb
  542. mov rES = _DataSelector
  543. mov rESD = rSSD
  544. mov rSS = _DataSelector
  545. mov rDS = _DataSelector
  546. mov rDSD = rSSD
  547. mov rCS = _CodeSelector
  548. mov rFS = _FsSelector
  549. ld2 v0 = [gp], 8
  550. add sp = -4, sp
  551. mov rLDT = _LdtSelector
  552. ;;
  553. ld8 rGDTD = [rIA32Ptr], 8
  554. // movl r3 = @fptr(_EM_IA_STUBRET_ExecuteX86HandlerStub)
  555. movl r3 = artificial_return
  556. ;;
  557. ld8 rLDTD = [rIA32Ptr], 8
  558. movl loc2 = JMPE_CONST
  559. ;;
  560. st4 [sp] = r3
  561. mov rGS = _DataSelector
  562. cmp.eq isTIA, isIA = loc2, v0
  563. ;;
  564. ld8 rFSD = [rIA32Ptr]
  565. (isTIA) ld8 r2 = [gp], 8
  566. br.ia.sptk bt0
  567. ;;
  568. ld8 gp = [gp]
  569. mov bt0 = r2
  570. br bt0
  571. LEAF_EXIT(_EM_IA_ExecuteHandler_Transition)
  572. LEAF_ENTRY(_EM_IA_STUBRET_ExecuteX86HandlerStub)
  573. //
  574. // Artifical return to the bundle following the call to ReX86Transition
  575. //
  576. artificial_return:
  577. .text
  578. data8 0xab80f
  579. data8 0x0
  580. nop.m 0
  581. nop.m 0
  582. br.ret.sptk brp
  583. LEAF_EXIT(_EM_IA_STUBRET_ExecuteX86HandlerStub)
  584. //++
  585. //
  586. // EXCEPTION_DISPOSITION
  587. // RtlpExecuteX86HandlerForUnwind (
  588. // IN PEXCEPTION_RECORD ExceptionRecord,
  589. // IN PVOID EstablisherFrame,
  590. // IN OUT PCONTEXT ContextRecord,
  591. // IN OUT PVOID DispatcherContext,
  592. // IN PEXCEPTION_ROUTINE ExceptionRoutine
  593. // )
  594. //
  595. // Routine Description:
  596. //
  597. // This function allocates a call frame, stores the establisher frame
  598. // pointer and the context record address in the frame, establishes an
  599. // exception handler, and then calls the specified exception handler as
  600. // an unwind handler. If a collided unwind occurs, then the exception
  601. // handler of of this function is called and the establisher frame pointer
  602. // and context record address are returned to the unwind dispatcher via
  603. // the dispatcher context parameter. If control is returned to this routine,
  604. // then the frame is deallocated and the disposition status is returned to
  605. // the unwind dispatcher.
  606. //
  607. // Arguments:
  608. //
  609. // ExceptionRecord (a0) - Supplies a pointer to an exception record.
  610. //
  611. // EstablisherFrame (a1) - Supplies the memory stack and backing store
  612. // frame pointers of the establisher whose exception handler is to
  613. // be called.
  614. //
  615. // ContextRecord (a2) - Supplies a pointer to a context record.
  616. //
  617. // DispatcherContext (a3) - Supplies a pointer to the dispatcher context
  618. // record.
  619. //
  620. // ExceptionRoutine (a4) - supplies a pointer to the exception handler
  621. // that is to be called.
  622. //
  623. // Return Value:
  624. //
  625. // The disposition value returned by the specified exception handler is
  626. // returned as the function value.
  627. //
  628. //--
  629. NESTED_ENTRY_EX(RtlpExecuteX86HandlerForUnwind, RtlpUnwindHandler)
  630. .regstk 5, 6, 0, 0
  631. .prologue 0xe, loc0
  632. alloc loc1 = ar.pfs, 5, 6, 0, 0
  633. mov loc2 = brp
  634. mov loc0 = sp
  635. PROLOGUE_END
  636. mov rTeb = teb
  637. add r13 = 4, sp
  638. mov r14 = sp
  639. mov loc3 = ar.fpsr
  640. sxt4 a3 = a3
  641. sxt4 gp = a4
  642. ;;
  643. mov rIA32Ptr = rIA32Rsrc
  644. st4 [r14] = a0, 8
  645. mov loc4 = pr
  646. ;;
  647. st4 [r13] = a1, 8
  648. st4 [r14] = a2, 16
  649. mov loc5 = ar.lc
  650. ;;
  651. st4 [r13] = a3
  652. mov bt0 = a4
  653. br.call.sptk brp = _EM_IA_ExecuteHandler_Transition
  654. mov ar.fpsr = loc3
  655. mov ar.pfs = loc0
  656. mov brp = loc1
  657. add sp = r0, loc2
  658. mov pr = loc4, -1
  659. mov ar.lc = loc5
  660. nop.m 0
  661. nop.m 0
  662. br.ret.sptk.clr brp
  663. NESTED_EXIT(RtlpExecuteX86HandlerForUnwind)
  664. #endif //0