windows-nt/Source/XPSP1/NT/base/win32/client/ia64/thunk.s
2020-09-26 16:20:57 +08:00

705 lines
16 KiB
ArmAsm
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//++
//
// 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