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.

371 lines
9.9 KiB

  1. //++
  2. //
  3. // Module Name:
  4. //
  5. // longjmp.s
  6. //
  7. // Abstract:
  8. //
  9. // This module implements the IA64 specific routine to perform a long
  10. // jump operation.
  11. //
  12. // N.B. This routine conditionally provides SAFE & UNSAFE handling of longjmp
  13. // which is NOT integrated with structured exception handling. The
  14. // determination is made based on whether the Type field
  15. // has been set to a nonzero value.
  16. //
  17. // N.B. Currently, this routine assumes the setjmp site is EM.
  18. // Support for iA setjmp site is to be finished.
  19. //
  20. // Author:
  21. //
  22. // William K. Cheung (wcheung) 30-Jan-1996
  23. //
  24. // Environment:
  25. //
  26. // Any mode.
  27. //
  28. // Revision History:
  29. //
  30. // Updated to EAS2.1.
  31. //
  32. //--
  33. #include "ksia64.h"
  34. //++
  35. //
  36. // int
  37. // longjmp (
  38. // IN jmp_buf JumpBuffer,
  39. // IN int ReturnValue
  40. // )
  41. //
  42. // Routine Description:
  43. //
  44. // This function performs a long jump to the context specified by the
  45. // jump buffer.
  46. //
  47. // Arguments:
  48. //
  49. // JumpBuffer (a0) - Supplies the address of a jump buffer that contains
  50. // jump information.
  51. //
  52. // ReturnValue (a1) - Supplies the value that is to be returned to the
  53. // caller of set jump.
  54. //
  55. // Return Value:
  56. //
  57. // None.
  58. //
  59. //--
  60. .global RtlUnwind2
  61. .type RtlUnwind2, @function
  62. NESTED_ENTRY(longjmp)
  63. NESTED_SETUP(2, 2, 6, 0)
  64. .fframe ExceptionRecordLength+ContextFrameLength
  65. add sp = -ExceptionRecordLength-ContextFrameLength, sp
  66. ARGPTR(a0)
  67. PROLOGUE_END
  68. mov t4 = ar.rsc
  69. cmp.eq pt1, pt0 = zero, a1
  70. add t6 = JbUnwindData, a0
  71. ;;
  72. ld8 out0 = [t6], 8 // get the UnwindData
  73. mov t2 = ar.bsp
  74. add t0 = JbIntNats, a0
  75. ;;
  76. //
  77. // If address of registration record is not equal to zero,
  78. // a safe longjmp is to be performed.
  79. //
  80. cmp.ne pt2, pt3 = zero, out0
  81. add t1 = JbBrS0, a0
  82. add t22 = JbIntS0, a0
  83. ;;
  84. (pt1) add a1 = 1, r0
  85. shr.u t22 = t22, 3
  86. ;;
  87. mov v0 = a1
  88. //
  89. // before restoring integer registers, restore their NaT bits so that
  90. // the load fills will recover them correctly.
  91. //
  92. (pt3) ld8 t7 = [t0], JbStIIP - JbIntNats
  93. (pt3) and t22 = 0x3f, t22
  94. (pt2) br.spnt Lj30
  95. mov ar.rsc = zero // put RSE in lazy mode
  96. ;;
  97. mov t3 = ar.bspstore
  98. cmp4.ge pt1, pt0 = 4, t22
  99. ;;
  100. //
  101. // at the same time, compute and shift the loaded preserved integer
  102. // registers' NaTs to the proper location.
  103. //
  104. ld8.nt1 t15 = [t0], JbBrS1 - JbStIIP
  105. ld8.nt1 t16 = [t1], JbBrS2 - JbBrS0
  106. (pt0) add t21 = -4, t22
  107. ;;
  108. ld8.nt1 t17 = [t0], JbBrS3 - JbBrS1
  109. ld8.nt1 t18 = [t1], JbBrS4 - JbBrS2
  110. (pt0) add t6 = 68, t22
  111. ;;
  112. ld8.nt1 t19 = [t0], JbRsBSP - JbBrS3
  113. ld8.nt1 t20 = [t1], JbRsPFS - JbBrS4
  114. (pt1) sub t21 = 4, t22
  115. ;;
  116. ld8.nt1 t10 = [t0], JbApUNAT - JbRsBSP
  117. ld8.nt1 t11 = [t1], JbApLC - JbRsPFS
  118. (pt0) shl t5 = t7, t21
  119. ;;
  120. ld8.nt1 t12 = [t0]
  121. ld8.nt1 t13 = [t1], JbPreds - JbApLC
  122. (pt0) shr.u t8 = t7, t6
  123. ;;
  124. ld8.nt1 t14 = [t1]
  125. (pt1) shr t9 = t7, t21
  126. (pt0) or t9 = t8, t5
  127. ;;
  128. extr.u t5 = t11, 7, 7 // local frame size
  129. extr.u t6 = t10, 3, 6 // rnat index
  130. ;;
  131. sub t8 = 63, t6
  132. mov t1 = t5
  133. ;;
  134. cmp.le pt2, pt1 = t8, t5
  135. ;;
  136. (pt2) add t1 = 1, t1
  137. (pt2) sub t5 = t5, t8
  138. (pt1) br.sptk Lj50
  139. ;;
  140. Lj40:
  141. cmp.le pt2, pt3 = 63, t5
  142. ;;
  143. (pt2) add t5 = -63, t5
  144. (pt2) add t1 = 1, t1
  145. (pt2) br.cond.dpnt Lj40
  146. ;;
  147. Lj50:
  148. shladd t10 = t1, 3, t10
  149. //
  150. // t2 = current bsp
  151. // t3 = current bspstore
  152. // t4 = saved rsc
  153. // t9 = NaTs of sp, s0 - s3
  154. // t10 = setjmp's bsp
  155. // t11 = setjmp's pfs
  156. // t12 = setjmp's unat
  157. // t13 = setjmp's loop counter
  158. // t14 = setjmp's predicates
  159. // t15 = setjmp's brp (StIIP)
  160. // t16 = setjmp's bs0
  161. // t17 = setjmp's bs1
  162. // t18 = setjmp's bs2
  163. // t19 = setjmp's bs3
  164. // t20 = setjmp's bs4
  165. //
  166. // Now UNAT contains the NaTs of the preserved integer registers
  167. // at bit positions corresponding to the locations from which the
  168. // integer registers can be restored (with load fill operations)
  169. //
  170. // Restore predicates and loop counter.
  171. //
  172. mov ar.unat = t9
  173. mov pr = t14, -1
  174. mov ar.lc = t13
  175. add t0 = JbFltS0, a0
  176. add t1 = JbFltS1, a0
  177. mov ar.pfs = t11
  178. ;;
  179. //
  180. // scratch registers t5 - t9, t11, t13, t14 are available for use.
  181. //
  182. // load preserved floating point states from jump buffer
  183. // move the loaded branch register states to the corresponding br registers
  184. //
  185. ldf.fill.nt1 fs0 = [t0], JbFltS2 - JbFltS0
  186. ldf.fill.nt1 fs1 = [t1], JbFltS3 - JbFltS1
  187. nop.i 0
  188. ;;
  189. ldf.fill.nt1 fs2 = [t0], JbFltS4 - JbFltS2
  190. ldf.fill.nt1 fs3 = [t1], JbFltS5 - JbFltS3
  191. mov brp = t15
  192. ;;
  193. ldf.fill.nt1 fs4 = [t0], JbFltS6 - JbFltS4
  194. ldf.fill.nt1 fs5 = [t1], JbFltS7 - JbFltS5
  195. mov bs0 = t16
  196. ;;
  197. ldf.fill.nt1 fs6 = [t0], JbFltS8 - JbFltS6
  198. ldf.fill.nt1 fs7 = [t1], JbFltS9 - JbFltS7
  199. mov bs1 = t17
  200. ;;
  201. ldf.fill.nt1 fs8 = [t0], JbFltS10 - JbFltS8
  202. ldf.fill.nt1 fs9 = [t1], JbFltS11 - JbFltS9
  203. mov bs2 = t18
  204. ;;
  205. ldf.fill.nt1 fs10 = [t0], JbFltS12 - JbFltS10
  206. ldf.fill.nt1 fs11 = [t1], JbFltS13 - JbFltS11
  207. mov bs3 = t19
  208. ;;
  209. ldf.fill.nt1 fs12 = [t0], JbFltS14 - JbFltS12
  210. ldf.fill.nt1 fs13 = [t1], JbFltS15 - JbFltS13
  211. mov bs4 = t20
  212. ;;
  213. ldf.fill.nt1 fs14 = [t0], JbFltS16 - JbFltS14
  214. ldf.fill.nt1 fs15 = [t1], JbFltS17 - JbFltS15
  215. brp.ret.sptk brp, Lj20
  216. ;;
  217. //
  218. // scratch registers t6 - t9, t11, t13 - t20 are available for use
  219. //
  220. // t2 is current bsp
  221. // t3 is current bspstore
  222. // t4 is saved rsc
  223. // t5 is the setjmp's fpsr
  224. // t10 is the setjmp's bsp
  225. // t12 is the setjmp's unat
  226. //
  227. ldf.fill.nt1 fs16 = [t0], JbFltS18 - JbFltS16
  228. ldf.fill.nt1 fs17 = [t1], JbFltS19 - JbFltS17
  229. cmp.lt p0, pt1 = t3, t10 // current bspstore < setjmp's bsp
  230. ;;
  231. ldf.fill.nt1 fs18 = [t0], JbFPSR - JbFltS18
  232. ldf.fill.nt1 fs19 = [t1], JbIntS1 - JbFltS19
  233. dep t9 = 1, t10, 3, 6 // OR 1s to get desired RNAT location
  234. ;; // t9 = OR(0x1f8, t10)
  235. mov t11 = ar.rnat // save rnat for later use
  236. ld8.nt1 t5 = [t0], JbIntS0 - JbFPSR
  237. (pt1) br.cond.spnt Lj10
  238. ;;
  239. flushrs // Flush the RSE and move up
  240. nop.m 0
  241. mov t3 = t2 // the current bspstore
  242. ;;
  243. Lj10:
  244. //
  245. // t3 is top of backing store in memory
  246. // t9 is desired RNAT collection location
  247. //
  248. ld8.fill.nt1 s0 = [t0], JbIntS2 - JbIntS0
  249. ld8.fill.nt1 s1 = [t1], JbIntS3 - JbIntS1
  250. cmp.lt pt1, pt2 = t3, t9 // current top of backing store
  251. ;; // is smaller than desired RNAT
  252. // collection location?
  253. // pt1: use RNAT app. register
  254. // pt2: load RNAT from bstore
  255. ld8.fill.nt1 s2 = [t0], JbIntSp - JbIntS2
  256. ld8.fill.nt1 s3 = [t1]
  257. nop.i 0
  258. ;;
  259. ld8.fill.nt1 t17 = [t0] // load setjmp's sp
  260. (pt2) ld8.nt1 t15 = [t9] // load desired RNAT
  261. nop.i 0
  262. ;;
  263. loadrs // invalidates dirty registers
  264. ;;
  265. mov ar.bspstore = t10 // set bspstore register
  266. ;;
  267. invala
  268. mov ar.unat = t12 // set unat
  269. mov sp = t17 // set stack pointer
  270. (pt2) mov ar.rnat = t15 // set rnat to loaded value
  271. (pt1) mov ar.rnat = t11 // reuse rnat content
  272. nop.i 0
  273. Lj20:
  274. mov ar.rsc = t4 // restore RSC
  275. ;;
  276. mov ar.fpsr = t5 // restore FPSR
  277. br.ret.sptk.clr brp // return to setjmp site
  278. Lj30:
  279. //
  280. // t6 -> UnwindData+8
  281. // out0 - target psp
  282. // out1 - target bsp
  283. // out2 - target ip (setjmp's StIIP)
  284. // out3 - exception record address
  285. // out4 - return value
  286. // out5 - context record address
  287. //
  288. add t5 = JbStIIP, a0
  289. add t0 = ErExceptionCode+STACK_SCRATCH_AREA, sp
  290. add t1 = ErExceptionFlags+STACK_SCRATCH_AREA, sp
  291. ;;
  292. ld8 out1 = [t6] // target bsp
  293. movl v0 = STATUS_LONGJUMP // get long jump status code
  294. ld8 out2 = [t5] // target ip
  295. st4 [t1] = zero, ErExceptionAddress - ErExceptionFlags
  296. add out3 = STACK_SCRATCH_AREA, sp
  297. ;;
  298. st4 [t0] = v0, ErExceptionInformation - ErExceptionCode
  299. STPTRINC(t1, zero, ErExceptionRecord - ErExceptionAddress)
  300. mov out4 = a1
  301. ;;
  302. STPTR(t0, a0)
  303. STPTRINC(t1, zero, ErNumberParameters - ErExceptionRecord)
  304. mov t4 = 1 // set to 1 argument
  305. ;;
  306. st4 [t1] = t4
  307. add out5 = STACK_SCRATCH_AREA+ExceptionRecordLength, sp
  308. br.call.sptk.many brp = RtlUnwind2 // call RtlUnwind2
  309. NESTED_EXIT(longjmp)