705 lines
16 KiB
ArmAsm
705 lines
16 KiB
ArmAsm
//++
|
||
//
|
||
// 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
|