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.

704 lines
16 KiB

  1. //++
  2. //
  3. // Module Name:
  4. //
  5. // thunk.s
  6. //
  7. // Abstract:
  8. //
  9. // This module implements all Win32 thunks. This includes the
  10. /// first level thread starter...
  11. //
  12. // Author:
  13. //
  14. // 12-Oct-1995
  15. //
  16. // Revision History:
  17. //
  18. //--
  19. #include "ksia64.h"
  20. .file "thunk.s"
  21. //++
  22. //
  23. // VOID
  24. // BaseThreadStartThunk(
  25. // IN PTHREAD_START_ROUTINE StartRoutine,
  26. // IN PVOID ThreadParameter
  27. // )
  28. //
  29. // Routine Description:
  30. //
  31. // This function calls to the portable thread starter after moving
  32. // its arguments from registers to the argument registers.
  33. //
  34. // Arguments:
  35. //
  36. // s1 - StartRoutine
  37. // s2 - ThreadParameter
  38. //
  39. // Return Value:
  40. //
  41. // Never Returns
  42. //
  43. //--
  44. PublicFunction(BaseThreadStart)
  45. LEAF_ENTRY(BaseThreadStartThunk)
  46. LEAF_SETUP(0,0,2,0)
  47. mov out0=s1
  48. mov out1=s2
  49. br.many BaseThreadStart
  50. ;;
  51. //
  52. // never come back here
  53. //
  54. LEAF_EXIT(BaseThreadStartThunk)
  55. //++
  56. //
  57. // VOID
  58. // BaseProcessStartThunk(
  59. // IN PTHREAD_START_ROUTINE StartRoutine,
  60. // IN PVOID ThreadParameter
  61. // )
  62. //
  63. // Routine Description:
  64. //
  65. // This function calls to the portable thread starter after moving
  66. // its arguments from registers to the argument registers.
  67. //
  68. // Arguments:
  69. //
  70. // s1 - StartRoutine
  71. // s2 - ThreadParameter
  72. //
  73. // Return Value:
  74. //
  75. // Never Returns
  76. //
  77. //--
  78. PublicFunction(BaseProcessStart)
  79. LEAF_ENTRY(BaseProcessStartThunk)
  80. alloc t22 = ar.pfs, 0, 0, 1, 0
  81. mov out0=s1
  82. br BaseProcessStart // jump process wrapper.
  83. ;;
  84. LEAF_EXIT(BaseProcessStartThunk)
  85. //++
  86. //
  87. // VOID
  88. // SwitchToFiber(
  89. // PFIBER NewFiber
  90. // )
  91. //
  92. // Routine Description:
  93. //
  94. // This function saves the state of the current fiber and switches
  95. // to the new fiber.
  96. //
  97. // Arguments:
  98. //
  99. // NewFiber (a0) - Supplies the address of the new fiber.
  100. //
  101. // Return Value:
  102. //
  103. // None
  104. //
  105. //--
  106. LEAF_ENTRY(SwitchToFiber)
  107. // local register aliases
  108. rOldFb = t21
  109. rOldCx = t20
  110. rNewFb = t19
  111. rNewCx = t18
  112. rA0 = t17
  113. dest1 = t10
  114. dest2 = t11
  115. dest4 = t12
  116. dest5 = t13
  117. //
  118. // set up pointers to old and new fiber and context records
  119. //
  120. add rNewFb = zero, a0
  121. add rNewCx = FbFiberContext, a0
  122. add t0 = TeFiberData, teb
  123. ;;
  124. LDPTR (t1, t0)
  125. mov rA0 = a0
  126. ;;
  127. add rOldFb = 0, t1
  128. add rOldCx = FbFiberContext, t1
  129. ;;
  130. //
  131. // step 1
  132. // save current state in to old fiber's fiber and context rec
  133. //
  134. //
  135. // save fiber exception list and stack info
  136. //
  137. add dest1 = TeExceptionList, teb // TEB
  138. add dest2 = FbExceptionList, rOldFb // Old fiber
  139. ;;
  140. LDPTRINC (t0, dest1, TeStackLimit - TeExceptionList)
  141. ;;
  142. STPTRINC (dest2, t0, FbStackLimit - FbExceptionList)
  143. ;;
  144. LDPTR (t0, dest1)
  145. ;;
  146. STPTR (dest2, t0)
  147. //
  148. // also save RSE stack info
  149. //
  150. add dest4 = TeBStoreLimit, teb
  151. add dest5 = FbBStoreLimit, rOldFb
  152. ;;
  153. LDPTR (t1, dest4)
  154. ;;
  155. STPTR (dest5, t1)
  156. ;;
  157. //
  158. // spill low non-volatile fp registers 0-3, 5-19
  159. //
  160. add dest1 = CxFltS0, rOldCx
  161. add dest2 = CxFltS1, rOldCx
  162. ;;
  163. mov t2 = ar.fpsr //FPSR
  164. mov t3 = ar28 //FSR
  165. mov t4 = ar29 //FIR
  166. mov t5 = ar30 //FDR
  167. stf.spill [dest1] = fs0, CxFltS2 - CxFltS0
  168. stf.spill [dest2] = fs1, CxFltS3 - CxFltS1
  169. ;;
  170. stf.spill [dest1] = fs2, CxFltS5 - CxFltS2
  171. stf.spill [dest2] = fs3, CxFltS6 - CxFltS3
  172. ;;
  173. stf.spill [dest1] = fs5, CxFltS7 - CxFltS5
  174. stf.spill [dest2] = fs6, CxFltS8 - CxFltS6
  175. ;;
  176. stf.spill [dest1] = fs7, CxFltS9 - CxFltS7
  177. stf.spill [dest2] = fs8, CxFltS10 - CxFltS8
  178. ;;
  179. stf.spill [dest1] = fs9, CxFltS11 - CxFltS9
  180. stf.spill [dest2] = fs10, CxFltS12 - CxFltS10
  181. ;;
  182. stf.spill [dest1] = fs11, CxFltS13 - CxFltS11
  183. stf.spill [dest2] = fs12, CxFltS14 - CxFltS12
  184. ;;
  185. stf.spill [dest1] = fs13, CxFltS15 - CxFltS13
  186. stf.spill [dest2] = fs14, CxFltS16 - CxFltS14
  187. ;;
  188. stf.spill [dest1] = fs15, CxFltS17 - CxFltS15
  189. stf.spill [dest2] = fs16, CxFltS18 - CxFltS16
  190. ;;
  191. stf.spill [dest1] = fs17, CxFltS19 - CxFltS17
  192. stf.spill [dest2] = fs18
  193. ;;
  194. stf.spill [dest1] = fs19
  195. //
  196. // fp status registers
  197. //
  198. add dest1 = CxStFPSR, rOldCx
  199. add dest2 = CxStFSR, rOldCx
  200. ;;
  201. st8 [dest1] = t2
  202. ;;
  203. st8 [dest2] = t3, CxStFDR - CxStFSR
  204. add dest1 = CxStFIR, rOldCx
  205. ;;
  206. st8 [dest1] = t4
  207. ;;
  208. st8 [dest2] = t5
  209. //
  210. // save old unat before starting the spills
  211. //
  212. mov t6 = ar.unat
  213. add dest4 = CxApUNAT, rOldCx
  214. ;;
  215. st8 [dest4] = t6
  216. mov ar.unat = zero
  217. ;;
  218. // ordering ? should not start spilling before unat is saved
  219. // save sp and preserved int registers
  220. add dest4 = CxIntS0, rOldCx
  221. add dest5 = CxIntSp, rOldCx
  222. ;;
  223. .mem.offset 0,0
  224. st8.spill [dest5] = sp, CxIntS1 - CxIntSp
  225. .mem.offset 8,0
  226. st8.spill [dest4] = s0, CxIntS2 - CxIntS0
  227. ;;
  228. .mem.offset 0,0
  229. st8.spill [dest5] = s1, CxIntS3 - CxIntS1
  230. .mem.offset 8,0
  231. st8.spill [dest4] = s2
  232. ;;
  233. st8.spill [dest5] = s3
  234. // save predicates
  235. add dest4 = CxPreds, rOldCx
  236. add dest5 = CxBrRp, rOldCx
  237. mov t7 = pr
  238. ;;
  239. st8 [dest4] = t7, CxBrS0 - CxPreds
  240. // save preserved branch registers
  241. mov t8 = brp
  242. ;;
  243. st8 [dest5] = t8, CxBrS1 - CxBrRp
  244. mov t9 = bs0
  245. ;;
  246. st8 [dest4] = t9, CxBrS2 - CxBrS0
  247. mov t1 = bs1
  248. ;;
  249. st8 [dest5] = t1, CxBrS3 - CxBrS1
  250. mov t2 = bs2
  251. ;;
  252. st8 [dest4] = t2, CxBrS4 - CxBrS2
  253. mov t3 = bs3
  254. ;;
  255. st8 [dest5] = t3
  256. mov t4 = bs4
  257. ;;
  258. st8 [dest4] = t4
  259. // save other applicatin registers
  260. //
  261. mov t6 = ar.lc
  262. add dest4 = CxApLC, rOldCx
  263. add dest5 = CxApEC, rOldCx
  264. ;;
  265. st8 [dest4] = t6, CxRsPFS - CxApLC
  266. mov t7 = ar.ec
  267. ;;
  268. st8 [dest5] = t7, CxRsRSC - CxApEC
  269. //
  270. // save RSE stuff
  271. //
  272. mov t8 = ar.pfs
  273. ;;
  274. st8 [dest4] = t8
  275. mov t9 = ar.rsc
  276. ;;
  277. st8 [dest5] = t9
  278. dep t9 = 0, t9, RSC_MODE, 2 // put in lazy mode
  279. ;;
  280. mov ar.rsc = t9
  281. //
  282. // since we do not use locals, we don't need cover..
  283. // cover
  284. // ;;
  285. ;;
  286. flushrs
  287. dep t9 = 0, t9, RSC_LOADRS, RSC_LOADRS_LEN // invalidate all
  288. ;;
  289. mov ar.rsc = t9
  290. ;;
  291. loadrs
  292. add dest1 = CxRsRNAT, rOldCx
  293. add dest2 = CxRsBSP, rOldCx
  294. ;;
  295. mov t1 = ar.bsp
  296. ;;
  297. st8 [dest2] = t1
  298. mov t2 = ar.rnat
  299. ;;
  300. st8 [dest1] = t2
  301. // save all spilled NaT bits in in IntNats
  302. add dest1 = CxIntNats, rOldCx
  303. mov t3 = ar.unat
  304. ;;
  305. st8 [dest1] = t3
  306. //
  307. // step 2
  308. // setup the state for new fiber from new context/fiber record
  309. //
  310. // restore exception list and stack info fist
  311. //
  312. add dest1 = TeExceptionList, teb
  313. add dest2 = FbExceptionList, rNewFb
  314. ;;
  315. LDPTRINC (t0, dest2, FbStackBase - FbExceptionList)
  316. ;;
  317. STPTRINC (dest1, t0, TeStackBase - TeExceptionList)
  318. ;;
  319. LDPTRINC (t0, dest2, FbStackLimit - FbStackBase)
  320. ;;
  321. STPTRINC (dest1, t0, TeStackLimit - TeStackBase)
  322. ;;
  323. LDPTR (t0, dest2)
  324. ;;
  325. STPTR (dest1, t0)
  326. add dest4 = TeDeallocationStack, teb
  327. add dest5 = FbDeallocationStack, rNewFb
  328. ;;
  329. LDPTR (t1, dest5)
  330. ;;
  331. STPTR (dest4, t1)
  332. // also restore RSE stack info
  333. //
  334. add dest4 = TeBStoreLimit, teb
  335. add dest5 = FbBStoreLimit, rNewFb
  336. ;;
  337. LDPTRINC (t2, dest5, FbDeallocationBStore - FbBStoreLimit)
  338. ;;
  339. STPTRINC (dest4, t2, TeDeallocationBStore - TeBStoreLimit)
  340. ;;
  341. LDPTR (t3, dest5)
  342. ;;
  343. STPTR (dest4, t3)
  344. // set the fiber pointer in teb to point to new fiber
  345. //
  346. add dest1 = TeFiberData, teb
  347. ;;
  348. STPTR (dest1, rA0)
  349. // set up new RSE first
  350. add dest1 = CxRsRSC, rNewCx
  351. add dest2 = CxRsBSP, rNewCx
  352. ;;
  353. ld8 t2 = [dest2], CxRsRNAT - CxRsBSP
  354. ;;
  355. mov ar.bspstore = t2
  356. invala
  357. ld8 t3 = [dest2]
  358. ;;
  359. mov ar.rnat = t3
  360. ld8 t4 = [dest1]
  361. ;;
  362. mov ar.rsc = t4
  363. add dest4 = CxRsPFS, rNewCx
  364. ;;
  365. ld8 t5 = [dest4]
  366. ;;
  367. mov ar.pfs = t5
  368. // restore floating point registers
  369. add dest1 = CxFltS0, rNewCx
  370. add dest2 = CxFltS1, rNewCx
  371. ;;
  372. ldf.fill fs0 = [dest1], CxFltS2 - CxFltS0
  373. ldf.fill fs1 = [dest2] , CxFltS3 - CxFltS1
  374. ;;
  375. ldf.fill fs2 = [dest1], CxFltS5 - CxFltS2
  376. ldf.fill fs3 = [dest2], CxFltS6 - CxFltS3
  377. ;;
  378. ldf.fill fs5 = [dest1], CxFltS7 - CxFltS5
  379. ldf.fill fs6 = [dest2], CxFltS8 - CxFltS6
  380. ;;
  381. ldf.fill fs7 = [dest1], CxFltS9 - CxFltS7
  382. ldf.fill fs8 = [dest2], CxFltS10 - CxFltS8
  383. ;;
  384. ldf.fill fs9 = [dest1], CxFltS11 - CxFltS9
  385. ldf.fill fs10 = [dest2], CxFltS12 - CxFltS10
  386. ;;
  387. ldf.fill fs11 = [dest1], CxFltS13 - CxFltS11
  388. ldf.fill fs12 = [dest2], CxFltS14 - CxFltS12
  389. ;;
  390. ldf.fill fs13 = [dest1], CxFltS15 - CxFltS13
  391. ldf.fill fs14 = [dest2], CxFltS16 - CxFltS14
  392. ;;
  393. ldf.fill fs15 = [dest1], CxFltS17 - CxFltS15
  394. ldf.fill fs16 = [dest2], CxFltS18 - CxFltS16
  395. ;;
  396. ldf.fill fs17 = [dest1], CxFltS19 - CxFltS17
  397. ldf.fill fs18 = [dest2]
  398. ;;
  399. ldf.fill fs19 = [dest1]
  400. add dest1 = CxStFPSR, rNewCx
  401. add dest2 = CxStFSR, rNewCx
  402. ;;
  403. ld8 t2 = [dest1] //FPSR
  404. ;;
  405. mov ar.fpsr = t2
  406. ld8 t3 = [dest2], CxStFDR - CxStFSR
  407. add dest1 = CxStFIR, rNewCx
  408. ;;
  409. mov ar28 = t3 //FSR
  410. ld8 t4 = [dest1]
  411. ;;
  412. mov ar29 = t4 //FIR
  413. ld8 t5 = [dest2]
  414. ;;
  415. mov ar30 = t5 //FDR
  416. //
  417. // restore ar.unat first, so that fills will restore the
  418. // nat bits correctly
  419. //
  420. add dest4 = CxIntNats, rNewCx
  421. ;;
  422. ld8 t6 = [dest4]
  423. ;;
  424. mov ar.unat = t6
  425. // now start filling the preserved integer registers
  426. //
  427. add dest4 = CxIntS0, rNewCx
  428. add dest5 = CxIntSp, rNewCx
  429. ;;
  430. ld8.fill sp = [dest5], CxIntS1 - CxIntSp
  431. // save preserved integer registers
  432. ld8.fill s0 = [dest4], CxIntS2 - CxIntS0
  433. ;;
  434. ld8.fill s1 = [dest5], CxIntS3 - CxIntS1
  435. ld8.fill s2 = [dest4]
  436. ;;
  437. ld8.fill s3 = [dest5]
  438. // restore predicates and branch registers
  439. add dest4 = CxPreds, rNewCx
  440. add dest5 = CxBrRp, rNewCx
  441. ;;
  442. ld8 t7 = [dest4], CxBrS0 - CxPreds
  443. ;;
  444. mov pr = t7
  445. ld8 t8 = [dest5], CxBrS1 - CxBrRp
  446. ;;
  447. mov brp = t8
  448. ld8 t9 = [dest4], CxBrS2 - CxBrS0
  449. ;;
  450. mov bs0 = t9
  451. ld8 t1 = [dest5], CxBrS3 - CxBrS1
  452. ;;
  453. mov bs1 = t1
  454. ld8 t2 = [dest4], CxBrS4 - CxBrS2
  455. ;;
  456. mov bs2 = t2
  457. ld8 t3 = [dest5]
  458. ;;
  459. mov bs3 = t3
  460. ld8 t4 = [dest4]
  461. ;;
  462. mov bs4 = t4
  463. // restore other applicatin registers
  464. //
  465. add dest4 = CxApLC, rNewCx
  466. add dest5 = CxApEC, rNewCx
  467. ;;
  468. ld8 t6 = [dest4]
  469. ;;
  470. mov ar.lc = t6
  471. ld8 t7 = [dest5]
  472. ;;
  473. mov ar.ec = t7
  474. // finally restore the unat register
  475. //
  476. add dest4 = CxApUNAT, rNewCx
  477. ;;
  478. ld8 t5 = [dest4]
  479. ;;
  480. mov ar.unat = t5
  481. br.ret.sptk brp
  482. //
  483. // this will execute BaseFiberStart if we are switching to
  484. // the new fiber for the first time. otherwise, it will
  485. // return back to new fiber.
  486. //
  487. LEAF_EXIT(SwitchToFiber)
  488. #if 0
  489. LEAF_ENTRY(GenericIACall)
  490. LEAF_SETUP(1,95,0,0)
  491. //
  492. // Load iA state for iVE. Since working with flat 32 in NT,
  493. // much of the state is a constant (per Freds document)
  494. //
  495. mov rBase = teb // Get TEB pointer
  496. // load up selector register constants, we dont care about GS
  497. mov rES = _DataSelector
  498. mov rSS = _DataSelector
  499. mov rDS = _DataSelector
  500. mov rGS = _DataSelector
  501. mov rCS = _CodeSelector
  502. mov rFS = _FsSelector
  503. mov rLDT = _LdtSelector
  504. //
  505. // Setup pointer to iA32 Resources relative to TEB
  506. //
  507. mov r23 = rIA32Rsrc
  508. add rIA32Ptr = rBase, r23
  509. ld8 rGDTD = [rIA32Ptr], 8 // load LDT Descriptor registers
  510. ld8 rLDTD = [rIA32Ptr], 8 // GDT Descriptor is 8 bytes after
  511. ld8 rFSD = [rIA32Ptr] // FSDescriptor is 8 bytes after
  512. //
  513. // Eflag should not be touched by stub routines...
  514. //
  515. //
  516. // Since CSD and SSD are in AR registers and since they are saved
  517. // on context switches, dont need to reload them...
  518. //
  519. //
  520. // DSD and ESD are the same as SSD, and we dont care about GSD
  521. //
  522. mov rESD = rSSD
  523. mov rDSD = rSSD
  524. mov rGSD = rSSD
  525. //
  526. // push the return address on the memory stack
  527. //
  528. //
  529. // As we never return, just push NULL...
  530. //
  531. //
  532. // Stack always points to a valid value, so decrement before putting on
  533. // return address
  534. //
  535. adds sp = -4, sp
  536. st4 [sp] = r0
  537. ARGPTR (in0)
  538. sxt4 r23 = in0
  539. mov b7 = r23
  540. br.ia.sptk b7
  541. //
  542. // Return addresses and stuff would go here, but we never return
  543. //
  544. LEAF_EXIT(GenericIACall)
  545. #endif