265 lines
6.6 KiB
ArmAsm
265 lines
6.6 KiB
ArmAsm
// TITLE("Win32 Thunks")
|
||
//++
|
||
//
|
||
// Copyright (c) 1990 Microsoft Corporation
|
||
//
|
||
// Module Name:
|
||
//
|
||
// thunk.s
|
||
//
|
||
// Abstract:
|
||
//
|
||
// This module implements Win32 functions that must be written in assembler.
|
||
//
|
||
// Author:
|
||
//
|
||
// Mark Lucovsky (markl) 5-Oct-1990
|
||
//
|
||
// Revision History:
|
||
//
|
||
// Thomas Van Baak (tvb) 21-Jul-1992
|
||
//
|
||
// Adapted for Alpha AXP.
|
||
//
|
||
//--
|
||
|
||
#include "ksalpha.h"
|
||
|
||
//
|
||
// Division by 10000 is accomplished using reciprocal multiplication.
|
||
// Define the magic muliplier and right shift values for this.
|
||
//
|
||
|
||
#define MAGIC_10000_MULTIPLY 0xd1b71758e219652c
|
||
#define MAGIC_10000_SHIFT 13
|
||
|
||
|
||
SBTTL("Switch Stack Then Terminate")
|
||
//++
|
||
//
|
||
// VOID
|
||
// BaseSwitchStackThenTerminate (
|
||
// IN PVOID StackLimit,
|
||
// IN PVOID NewStack,
|
||
// IN DWORD ExitCode
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// This API is called during thread termination to delete a thread's
|
||
// stack, switch to a stack in the thread's TEB, and then terminate.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// StackLimit (a0) - Supplies the address of the stack to be freed.
|
||
//
|
||
// NewStack (a1) - Supplies an address within the terminating thread's TE
|
||
// that is to be used as its temporary stack while exiting.
|
||
//
|
||
// ExitCode (a2) - Supplies the termination status that the thread
|
||
// is to exit with.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// None.
|
||
//
|
||
//--
|
||
|
||
LEAF_ENTRY(BaseSwitchStackThenTerminate)
|
||
|
||
//
|
||
// Switch stacks and then jump to BaseFreeStackAndTerminate.
|
||
//
|
||
|
||
mov a1, sp // set new stack pointer
|
||
mov a2, a1 // set exit code argument
|
||
br zero, BaseFreeStackAndTerminate // jump
|
||
|
||
.end BaseSwitchStackThenTerminate
|
||
|
||
SBTTL("Base Attach Complete")
|
||
//++
|
||
//
|
||
// The following code is never executed. Its purpose is to support unwinding
|
||
// through the call to the exception dispatcher.
|
||
//
|
||
//--
|
||
|
||
NESTED_ENTRY(BaseAttachCompThunk, ContextFrameLength, zero);
|
||
|
||
.set noreorder
|
||
.set noat
|
||
|
||
lda sp, -ContextFrameLength(sp) // allocate stack frame
|
||
stq sp, CxIntSp(sp) // save stack pointer
|
||
stq ra, CxIntRa(sp) // save return address
|
||
stq ra, CxFir(sp) // mark continuation address location
|
||
stq fp, CxIntFp(sp) // save integer register fp/s6
|
||
stq gp, CxIntGp(sp) // save integer register gp
|
||
|
||
stq s0, CxIntS0(sp) // save integer registers s0 - s5
|
||
stq s1, CxIntS1(sp) //
|
||
stq s2, CxIntS2(sp) //
|
||
stq s3, CxIntS3(sp) //
|
||
stq s4, CxIntS4(sp) //
|
||
stq s5, CxIntS5(sp) //
|
||
|
||
stt f2, CxFltF2(sp) // store floating registers f2 - f9
|
||
stt f3, CxFltF3(sp) //
|
||
stt f4, CxFltF4(sp) //
|
||
stt f5, CxFltF5(sp) //
|
||
stt f6, CxFltF6(sp) //
|
||
stt f7, CxFltF7(sp) //
|
||
stt f8, CxFltF8(sp) //
|
||
stt f9, CxFltF9(sp) //
|
||
|
||
.set at
|
||
.set reorder
|
||
|
||
PROLOGUE_END
|
||
//++
|
||
//
|
||
// VOID
|
||
// BaseAttachCompleteThunk (
|
||
// VOID
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// This function is called after a successful debug attach. Its
|
||
// purpose is to call portable code that does a breakpoint, followed
|
||
// by an NtContinue.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// None.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// None.
|
||
//
|
||
//--
|
||
ALTERNATE_ENTRY(BaseAttachCompleteThunk)
|
||
|
||
mov s0, a0 // set context frame address argument
|
||
br zero, BaseAttachComplete // jump
|
||
|
||
.end BaseAttachCompThunk
|
||
|
||
|
||
//++
|
||
//
|
||
// VOID
|
||
// WINAPI
|
||
// SwitchToFiber (
|
||
// LPVOID lpFiber
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// This function saves the state of the current fiber and switches
|
||
// to the new fiber.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// CurrentFiber - Supplies the address of the current fiber.
|
||
//
|
||
// NewFiber - Supplies the address of the new fiber.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// None.
|
||
//
|
||
//--
|
||
LEAF_ENTRY(SwitchToFiber)
|
||
|
||
GET_THREAD_ENVIRONMENT_BLOCK // get TEB in v0
|
||
|
||
//
|
||
// Get current fiber
|
||
//
|
||
ldl a1, TeFiberData(v0)
|
||
|
||
//
|
||
// Set new deallocation stack and fiberdata in TEB
|
||
//
|
||
ldl t0, FbDeallocationStack(a0)
|
||
stl t0, TeDeallocationStack(v0)
|
||
stl a0, TeFiberData(v0)
|
||
|
||
//
|
||
// Save stack limit.
|
||
//
|
||
ldl t1, TeStackLimit(v0)
|
||
stl t1, FbStackLimit(a1) // save StackLimit
|
||
|
||
//
|
||
// Save nonvolatile integer state
|
||
//
|
||
stq s0, CxIntS0+FbFiberContext(a1)
|
||
stq s1, CxIntS1+FbFiberContext(a1)
|
||
stq s2, CxIntS2+FbFiberContext(a1)
|
||
stq s3, CxIntS3+FbFiberContext(a1)
|
||
stq s4, CxIntS4+FbFiberContext(a1)
|
||
stq s5, CxIntS5+FbFiberContext(a1)
|
||
stq fp, CxIntFp+FbFiberContext(a1)
|
||
|
||
//
|
||
// Save nonvolatile float state
|
||
//
|
||
stt f2, CxFltF2+FbFiberContext(a1)
|
||
stt f3, CxFltF3+FbFiberContext(a1)
|
||
stt f4, CxFltF4+FbFiberContext(a1)
|
||
stt f5, CxFltF5+FbFiberContext(a1)
|
||
stt f6, CxFltF6+FbFiberContext(a1)
|
||
stt f7, CxFltF7+FbFiberContext(a1)
|
||
stt f8, CxFltF8+FbFiberContext(a1)
|
||
stt f9, CxFltF9+FbFiberContext(a1)
|
||
|
||
//
|
||
// Save RA and SP
|
||
//
|
||
stq ra, CxFir+FbFiberContext(a1)
|
||
stq sp, CxIntSp+FbFiberContext(a1)
|
||
|
||
//
|
||
// Restore new fiber's stack base and stack limit
|
||
//
|
||
ldl t0, FbStackBase(a0) // restore StackBase
|
||
stl t0, TeStackBase(v0)
|
||
ldl t1, FbStackLimit(a0) // restore StackLimit
|
||
stl t1, TeStackLimit(v0)
|
||
|
||
//
|
||
// Restore nonvolatile integer state
|
||
//
|
||
ldq s0, CxIntS0+FbFiberContext(a0)
|
||
ldq s1, CxIntS1+FbFiberContext(a0)
|
||
ldq s2, CxIntS2+FbFiberContext(a0)
|
||
ldq s3, CxIntS3+FbFiberContext(a0)
|
||
ldq s4, CxIntS4+FbFiberContext(a0)
|
||
ldq s5, CxIntS5+FbFiberContext(a0)
|
||
ldq fp, CxIntFp+FbFiberContext(a0)
|
||
|
||
//
|
||
// Restore nonvolatile float state
|
||
//
|
||
ldt f2, CxFltF2+FbFiberContext(a0)
|
||
ldt f3, CxFltF3+FbFiberContext(a0)
|
||
ldt f4, CxFltF4+FbFiberContext(a0)
|
||
ldt f5, CxFltF5+FbFiberContext(a0)
|
||
ldt f6, CxFltF6+FbFiberContext(a0)
|
||
ldt f7, CxFltF7+FbFiberContext(a0)
|
||
ldt f8, CxFltF8+FbFiberContext(a0)
|
||
ldt f9, CxFltF9+FbFiberContext(a0)
|
||
|
||
//
|
||
// Restore RA and SP
|
||
//
|
||
ldq ra, CxFir+FbFiberContext(a0)
|
||
ldq sp, CxIntSp+FbFiberContext(a0)
|
||
|
||
ret zero, (ra)
|
||
|
||
.end BasepSwitchToFiber
|