//++ // // Module Name: // // thunk.s // // Abstract: // // This module implements all Win32 thunks. This includes the /// first level thread starter... // // Author: // // 12-Oct-1995 // // Revision History: // //-- #include "ksia64.h" .file "thunk.s" //++ // // VOID // BaseThreadStartThunk( // IN PTHREAD_START_ROUTINE StartRoutine, // IN PVOID ThreadParameter // ) // // Routine Description: // // This function calls to the portable thread starter after moving // its arguments from registers to the argument registers. // // Arguments: // // s1 - StartRoutine // s2 - ThreadParameter // // Return Value: // // Never Returns // //-- PublicFunction(BaseThreadStart) LEAF_ENTRY(BaseThreadStartThunk) LEAF_SETUP(0,0,2,0) mov out0=s1 mov out1=s2 br.many BaseThreadStart ;; // // never come back here // LEAF_EXIT(BaseThreadStartThunk) //++ // // VOID // BaseProcessStartThunk( // IN PTHREAD_START_ROUTINE StartRoutine, // IN PVOID ThreadParameter // ) // // Routine Description: // // This function calls to the portable thread starter after moving // its arguments from registers to the argument registers. // // Arguments: // // s1 - StartRoutine // s2 - ThreadParameter // // Return Value: // // Never Returns // //-- PublicFunction(BaseProcessStart) LEAF_ENTRY(BaseProcessStartThunk) alloc t22 = ar.pfs, 0, 0, 1, 0 mov out0=s1 br BaseProcessStart // jump process wrapper. ;; LEAF_EXIT(BaseProcessStartThunk) //++ // // VOID // SwitchToFiber( // PFIBER NewFiber // ) // // Routine Description: // // This function saves the state of the current fiber and switches // to the new fiber. // // Arguments: // // NewFiber (a0) - Supplies the address of the new fiber. // // Return Value: // // None // //-- LEAF_ENTRY(SwitchToFiber) // local register aliases rOldFb = t21 rOldCx = t20 rNewFb = t19 rNewCx = t18 rA0 = t17 dest1 = t10 dest2 = t11 dest4 = t12 dest5 = t13 // // set up pointers to old and new fiber and context records // add rNewFb = zero, a0 add rNewCx = FbFiberContext, a0 add t0 = TeFiberData, teb ;; LDPTR (t1, t0) mov rA0 = a0 ;; add rOldFb = 0, t1 add rOldCx = FbFiberContext, t1 ;; // // step 1 // save current state in to old fiber's fiber and context rec // // // save fiber exception list and stack info // add dest1 = TeExceptionList, teb // TEB add dest2 = FbExceptionList, rOldFb // Old fiber ;; LDPTRINC (t0, dest1, TeStackLimit - TeExceptionList) ;; STPTRINC (dest2, t0, FbStackLimit - FbExceptionList) ;; LDPTR (t0, dest1) ;; STPTR (dest2, t0) // // also save RSE stack info // add dest4 = TeBStoreLimit, teb add dest5 = FbBStoreLimit, rOldFb ;; LDPTR (t1, dest4) ;; STPTR (dest5, t1) ;; // // spill low non-volatile fp registers 0-3, 5-19 // add dest1 = CxFltS0, rOldCx add dest2 = CxFltS1, rOldCx ;; mov t2 = ar.fpsr //FPSR mov t3 = ar28 //FSR mov t4 = ar29 //FIR mov t5 = ar30 //FDR stf.spill [dest1] = fs0, CxFltS2 - CxFltS0 stf.spill [dest2] = fs1, CxFltS3 - CxFltS1 ;; stf.spill [dest1] = fs2, CxFltS5 - CxFltS2 stf.spill [dest2] = fs3, CxFltS6 - CxFltS3 ;; stf.spill [dest1] = fs5, CxFltS7 - CxFltS5 stf.spill [dest2] = fs6, CxFltS8 - CxFltS6 ;; stf.spill [dest1] = fs7, CxFltS9 - CxFltS7 stf.spill [dest2] = fs8, CxFltS10 - CxFltS8 ;; stf.spill [dest1] = fs9, CxFltS11 - CxFltS9 stf.spill [dest2] = fs10, CxFltS12 - CxFltS10 ;; stf.spill [dest1] = fs11, CxFltS13 - CxFltS11 stf.spill [dest2] = fs12, CxFltS14 - CxFltS12 ;; stf.spill [dest1] = fs13, CxFltS15 - CxFltS13 stf.spill [dest2] = fs14, CxFltS16 - CxFltS14 ;; stf.spill [dest1] = fs15, CxFltS17 - CxFltS15 stf.spill [dest2] = fs16, CxFltS18 - CxFltS16 ;; stf.spill [dest1] = fs17, CxFltS19 - CxFltS17 stf.spill [dest2] = fs18 ;; stf.spill [dest1] = fs19 // // fp status registers // add dest1 = CxStFPSR, rOldCx add dest2 = CxStFSR, rOldCx ;; st8 [dest1] = t2 ;; st8 [dest2] = t3, CxStFDR - CxStFSR add dest1 = CxStFIR, rOldCx ;; st8 [dest1] = t4 ;; st8 [dest2] = t5 // // save old unat before starting the spills // mov t6 = ar.unat add dest4 = CxApUNAT, rOldCx ;; st8 [dest4] = t6 mov ar.unat = zero ;; // ordering ? should not start spilling before unat is saved // save sp and preserved int registers add dest4 = CxIntS0, rOldCx add dest5 = CxIntSp, rOldCx ;; .mem.offset 0,0 st8.spill [dest5] = sp, CxIntS1 - CxIntSp .mem.offset 8,0 st8.spill [dest4] = s0, CxIntS2 - CxIntS0 ;; .mem.offset 0,0 st8.spill [dest5] = s1, CxIntS3 - CxIntS1 .mem.offset 8,0 st8.spill [dest4] = s2 ;; st8.spill [dest5] = s3 // save predicates add dest4 = CxPreds, rOldCx add dest5 = CxBrRp, rOldCx mov t7 = pr ;; st8 [dest4] = t7, CxBrS0 - CxPreds // save preserved branch registers mov t8 = brp ;; st8 [dest5] = t8, CxBrS1 - CxBrRp mov t9 = bs0 ;; st8 [dest4] = t9, CxBrS2 - CxBrS0 mov t1 = bs1 ;; st8 [dest5] = t1, CxBrS3 - CxBrS1 mov t2 = bs2 ;; st8 [dest4] = t2, CxBrS4 - CxBrS2 mov t3 = bs3 ;; st8 [dest5] = t3 mov t4 = bs4 ;; st8 [dest4] = t4 // save other applicatin registers // mov t6 = ar.lc add dest4 = CxApLC, rOldCx add dest5 = CxApEC, rOldCx ;; st8 [dest4] = t6, CxRsPFS - CxApLC mov t7 = ar.ec ;; st8 [dest5] = t7, CxRsRSC - CxApEC // // save RSE stuff // mov t8 = ar.pfs ;; st8 [dest4] = t8 mov t9 = ar.rsc ;; st8 [dest5] = t9 dep t9 = 0, t9, RSC_MODE, 2 // put in lazy mode ;; mov ar.rsc = t9 // // since we do not use locals, we don't need cover.. // cover // ;; ;; flushrs dep t9 = 0, t9, RSC_LOADRS, RSC_LOADRS_LEN // invalidate all ;; mov ar.rsc = t9 ;; loadrs add dest1 = CxRsRNAT, rOldCx add dest2 = CxRsBSP, rOldCx ;; mov t1 = ar.bsp ;; st8 [dest2] = t1 mov t2 = ar.rnat ;; st8 [dest1] = t2 // save all spilled NaT bits in in IntNats add dest1 = CxIntNats, rOldCx mov t3 = ar.unat ;; st8 [dest1] = t3 // // step 2 // setup the state for new fiber from new context/fiber record // // restore exception list and stack info fist // add dest1 = TeExceptionList, teb add dest2 = FbExceptionList, rNewFb ;; LDPTRINC (t0, dest2, FbStackBase - FbExceptionList) ;; STPTRINC (dest1, t0, TeStackBase - TeExceptionList) ;; LDPTRINC (t0, dest2, FbStackLimit - FbStackBase) ;; STPTRINC (dest1, t0, TeStackLimit - TeStackBase) ;; LDPTR (t0, dest2) ;; STPTR (dest1, t0) add dest4 = TeDeallocationStack, teb add dest5 = FbDeallocationStack, rNewFb ;; LDPTR (t1, dest5) ;; STPTR (dest4, t1) // also restore RSE stack info // add dest4 = TeBStoreLimit, teb add dest5 = FbBStoreLimit, rNewFb ;; LDPTRINC (t2, dest5, FbDeallocationBStore - FbBStoreLimit) ;; STPTRINC (dest4, t2, TeDeallocationBStore - TeBStoreLimit) ;; LDPTR (t3, dest5) ;; STPTR (dest4, t3) // set the fiber pointer in teb to point to new fiber // add dest1 = TeFiberData, teb ;; STPTR (dest1, rA0) // set up new RSE first add dest1 = CxRsRSC, rNewCx add dest2 = CxRsBSP, rNewCx ;; ld8 t2 = [dest2], CxRsRNAT - CxRsBSP ;; mov ar.bspstore = t2 invala ld8 t3 = [dest2] ;; mov ar.rnat = t3 ld8 t4 = [dest1] ;; mov ar.rsc = t4 add dest4 = CxRsPFS, rNewCx ;; ld8 t5 = [dest4] ;; mov ar.pfs = t5 // restore floating point registers add dest1 = CxFltS0, rNewCx add dest2 = CxFltS1, rNewCx ;; ldf.fill fs0 = [dest1], CxFltS2 - CxFltS0 ldf.fill fs1 = [dest2] , CxFltS3 - CxFltS1 ;; ldf.fill fs2 = [dest1], CxFltS5 - CxFltS2 ldf.fill fs3 = [dest2], CxFltS6 - CxFltS3 ;; ldf.fill fs5 = [dest1], CxFltS7 - CxFltS5 ldf.fill fs6 = [dest2], CxFltS8 - CxFltS6 ;; ldf.fill fs7 = [dest1], CxFltS9 - CxFltS7 ldf.fill fs8 = [dest2], CxFltS10 - CxFltS8 ;; ldf.fill fs9 = [dest1], CxFltS11 - CxFltS9 ldf.fill fs10 = [dest2], CxFltS12 - CxFltS10 ;; ldf.fill fs11 = [dest1], CxFltS13 - CxFltS11 ldf.fill fs12 = [dest2], CxFltS14 - CxFltS12 ;; ldf.fill fs13 = [dest1], CxFltS15 - CxFltS13 ldf.fill fs14 = [dest2], CxFltS16 - CxFltS14 ;; ldf.fill fs15 = [dest1], CxFltS17 - CxFltS15 ldf.fill fs16 = [dest2], CxFltS18 - CxFltS16 ;; ldf.fill fs17 = [dest1], CxFltS19 - CxFltS17 ldf.fill fs18 = [dest2] ;; ldf.fill fs19 = [dest1] add dest1 = CxStFPSR, rNewCx add dest2 = CxStFSR, rNewCx ;; ld8 t2 = [dest1] //FPSR ;; mov ar.fpsr = t2 ld8 t3 = [dest2], CxStFDR - CxStFSR add dest1 = CxStFIR, rNewCx ;; mov ar28 = t3 //FSR ld8 t4 = [dest1] ;; mov ar29 = t4 //FIR ld8 t5 = [dest2] ;; mov ar30 = t5 //FDR // // restore ar.unat first, so that fills will restore the // nat bits correctly // add dest4 = CxIntNats, rNewCx ;; ld8 t6 = [dest4] ;; mov ar.unat = t6 // now start filling the preserved integer registers // add dest4 = CxIntS0, rNewCx add dest5 = CxIntSp, rNewCx ;; ld8.fill sp = [dest5], CxIntS1 - CxIntSp // save preserved integer registers ld8.fill s0 = [dest4], CxIntS2 - CxIntS0 ;; ld8.fill s1 = [dest5], CxIntS3 - CxIntS1 ld8.fill s2 = [dest4] ;; ld8.fill s3 = [dest5] // restore predicates and branch registers add dest4 = CxPreds, rNewCx add dest5 = CxBrRp, rNewCx ;; ld8 t7 = [dest4], CxBrS0 - CxPreds ;; mov pr = t7 ld8 t8 = [dest5], CxBrS1 - CxBrRp ;; mov brp = t8 ld8 t9 = [dest4], CxBrS2 - CxBrS0 ;; mov bs0 = t9 ld8 t1 = [dest5], CxBrS3 - CxBrS1 ;; mov bs1 = t1 ld8 t2 = [dest4], CxBrS4 - CxBrS2 ;; mov bs2 = t2 ld8 t3 = [dest5] ;; mov bs3 = t3 ld8 t4 = [dest4] ;; mov bs4 = t4 // restore other applicatin registers // add dest4 = CxApLC, rNewCx add dest5 = CxApEC, rNewCx ;; ld8 t6 = [dest4] ;; mov ar.lc = t6 ld8 t7 = [dest5] ;; mov ar.ec = t7 // finally restore the unat register // add dest4 = CxApUNAT, rNewCx ;; ld8 t5 = [dest4] ;; mov ar.unat = t5 br.ret.sptk brp // // this will execute BaseFiberStart if we are switching to // the new fiber for the first time. otherwise, it will // return back to new fiber. // LEAF_EXIT(SwitchToFiber) #if 0 LEAF_ENTRY(GenericIACall) LEAF_SETUP(1,95,0,0) // // Load iA state for iVE. Since working with flat 32 in NT, // much of the state is a constant (per Freds document) // mov rBase = teb // Get TEB pointer // load up selector register constants, we dont care about GS mov rES = _DataSelector mov rSS = _DataSelector mov rDS = _DataSelector mov rGS = _DataSelector mov rCS = _CodeSelector mov rFS = _FsSelector mov rLDT = _LdtSelector // // Setup pointer to iA32 Resources relative to TEB // mov r23 = rIA32Rsrc add rIA32Ptr = rBase, r23 ld8 rGDTD = [rIA32Ptr], 8 // load LDT Descriptor registers ld8 rLDTD = [rIA32Ptr], 8 // GDT Descriptor is 8 bytes after ld8 rFSD = [rIA32Ptr] // FSDescriptor is 8 bytes after // // Eflag should not be touched by stub routines... // // // Since CSD and SSD are in AR registers and since they are saved // on context switches, dont need to reload them... // // // DSD and ESD are the same as SSD, and we dont care about GSD // mov rESD = rSSD mov rDSD = rSSD mov rGSD = rSSD // // push the return address on the memory stack // // // As we never return, just push NULL... // // // Stack always points to a valid value, so decrement before putting on // return address // adds sp = -4, sp st4 [sp] = r0 ARGPTR (in0) sxt4 r23 = in0 mov b7 = r23 br.ia.sptk b7 // // Return addresses and stuff would go here, but we never return // LEAF_EXIT(GenericIACall) #endif