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.
700 lines
17 KiB
700 lines
17 KiB
//++
|
|
//
|
|
// 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
|
|
;;
|
|
|
|
ld8 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
|
|
//
|
|
|
|
flushrs
|
|
add dest1 = TeExceptionList, teb // TEB
|
|
add dest2 = FbExceptionList, rOldFb // Old fiber
|
|
|
|
//
|
|
// also save RSE stack info
|
|
//
|
|
|
|
add dest4 = TeBStoreLimit, teb
|
|
add dest5 = FbBStoreLimit, rOldFb
|
|
;;
|
|
|
|
ld8 t0 = [dest1], TeStackLimit - TeExceptionList
|
|
ld8 t1 = [dest4], TeFlsData - TeBStoreLimit
|
|
;;
|
|
st8 [dest2] = t0, FbStackLimit - FbExceptionList
|
|
st8 [dest5] = t1, FbFlsData - FbBStoreLimit
|
|
;;
|
|
|
|
ld8 t0 = [dest1]
|
|
ld8 t1 = [dest4]
|
|
;;
|
|
st8 [dest2] = t0
|
|
st8 [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, CxFltS4 - CxFltS2
|
|
stf.spill [dest2] = fs3, CxFltS5 - CxFltS3
|
|
;;
|
|
|
|
stf.spill [dest1] = fs4, CxFltS6 - CxFltS4
|
|
stf.spill [dest2] = fs5, CxFltS7 - CxFltS5
|
|
;;
|
|
|
|
stf.spill [dest1] = fs6, CxFltS8 - CxFltS6
|
|
stf.spill [dest2] = fs7, CxFltS9 - CxFltS7
|
|
;;
|
|
|
|
stf.spill [dest1] = fs8, CxFltS10 - CxFltS8
|
|
stf.spill [dest2] = fs9, CxFltS11 - CxFltS9
|
|
;;
|
|
|
|
stf.spill [dest1] = fs10, CxFltS12 - CxFltS10
|
|
stf.spill [dest2] = fs11, CxFltS13 - CxFltS11
|
|
;;
|
|
|
|
stf.spill [dest1] = fs12, CxFltS14 - CxFltS12
|
|
stf.spill [dest2] = fs13, CxFltS15 - CxFltS13
|
|
;;
|
|
|
|
stf.spill [dest1] = fs14, CxFltS16 - CxFltS14
|
|
stf.spill [dest2] = fs15, CxFltS17 - CxFltS15
|
|
;;
|
|
|
|
stf.spill [dest1] = fs16, CxFltS18 - CxFltS16
|
|
stf.spill [dest2] = fs17, CxFltS19 - CxFltS17
|
|
;;
|
|
|
|
stf.spill [dest1] = fs18
|
|
stf.spill [dest2] = 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
|
|
// ;;
|
|
|
|
;;
|
|
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
|
|
add dest4 = TeBStoreLimit, teb
|
|
add dest5 = FbBStoreLimit, rNewFb
|
|
;;
|
|
|
|
ld8 t0 = [dest2], FbStackBase - FbExceptionList
|
|
ld8 t2 = [dest5], FbDeallocationBStore - FbBStoreLimit
|
|
;;
|
|
st8 [dest1] = t0, TeStackBase - TeExceptionList
|
|
st8 [dest4] = t2, TeDeallocationBStore - TeBStoreLimit
|
|
;;
|
|
|
|
ld8 t0 = [dest2], FbStackLimit - FbStackBase
|
|
ld8 t2 = [dest5], FbFlsData - FbDeallocationBStore
|
|
;;
|
|
st8 [dest1] = t0, TeStackLimit - TeStackBase
|
|
st8 [dest4] = t2, TeFlsData - TeDeallocationBStore
|
|
;;
|
|
|
|
ld8 t0 = [dest2]
|
|
ld8 t1 = [dest5]
|
|
|
|
;;
|
|
st8 [dest1] = t0
|
|
st8 [dest4] = t1
|
|
add dest5 = FbDeallocationStack, rNewFb
|
|
add dest4 = TeDeallocationStack, teb
|
|
add dest1 = TeFiberData, teb
|
|
|
|
;;
|
|
|
|
ld8 t3 = [dest5]
|
|
|
|
//
|
|
// set the fiber pointer in teb to point to new fiber
|
|
//
|
|
|
|
st8 [dest1] = rA0
|
|
add dest2 = CxRsBSP, rNewCx
|
|
;;
|
|
|
|
|
|
st8 [dest4] = t3
|
|
ld8 t2 = [dest2], CxRsRNAT - CxRsBSP
|
|
add dest1 = CxRsRSC, rNewCx
|
|
;;
|
|
|
|
;;
|
|
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], CxFltS4 - CxFltS2
|
|
ldf.fill fs3 = [dest2], CxFltS5 - CxFltS3
|
|
;;
|
|
|
|
ldf.fill fs4 = [dest1], CxFltS6 - CxFltS4
|
|
ldf.fill fs5 = [dest2], CxFltS7 - CxFltS5
|
|
;;
|
|
|
|
ldf.fill fs6 = [dest1], CxFltS8 - CxFltS6
|
|
ldf.fill fs7 = [dest2], CxFltS9 - CxFltS7
|
|
;;
|
|
|
|
ldf.fill fs8 = [dest1], CxFltS10 - CxFltS8
|
|
ldf.fill fs9 = [dest2], CxFltS11 - CxFltS9
|
|
;;
|
|
|
|
ldf.fill fs10 = [dest1], CxFltS12 - CxFltS10
|
|
ldf.fill fs11 = [dest2], CxFltS13 - CxFltS11
|
|
;;
|
|
|
|
ldf.fill fs12 = [dest1], CxFltS14 - CxFltS12
|
|
ldf.fill fs13 = [dest2], CxFltS15 - CxFltS13
|
|
;;
|
|
|
|
ldf.fill fs14 = [dest1], CxFltS16 - CxFltS14
|
|
ldf.fill fs15 = [dest2], CxFltS17 - CxFltS15
|
|
;;
|
|
|
|
ldf.fill fs16 = [dest1], CxFltS18 - CxFltS16
|
|
ldf.fill fs17 = [dest2], CxFltS19 - CxFltS17
|
|
;;
|
|
|
|
ldf.fill fs18 = [dest1]
|
|
ldf.fill fs19 = [dest2]
|
|
|
|
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
|