353 lines
10 KiB
ArmAsm
353 lines
10 KiB
ArmAsm
// TITLE("Win32 Thunks")
|
|
//++
|
|
//
|
|
// Copyright (c) 1993 IBM Corporation
|
|
//
|
|
// Module Name:
|
|
//
|
|
// thunk.s
|
|
//
|
|
// Abstract:
|
|
//
|
|
// This module implements Win32 functions that must be written in
|
|
// macro.
|
|
//
|
|
// Author:
|
|
//
|
|
// Curt Fawcett (crf) 22-Sept-1993
|
|
//
|
|
// Revision History:
|
|
//
|
|
// Curt Fawcett (crf) 19-Jan-1994 Removed Register names
|
|
// as requested
|
|
//--
|
|
//
|
|
// Parameter Register Usage:
|
|
//
|
|
// r.3 - Current time low part
|
|
// r.4 - Current time high part
|
|
// r.5 - Boot time low part
|
|
// r.6 - Boot time high part
|
|
//
|
|
// r.4 - New stack address
|
|
// r.5 - Exit code
|
|
//
|
|
// Local Register Usage:
|
|
//
|
|
// r.7 - Result low part
|
|
// r.8 - Result high part
|
|
// r.9 - Temporary high part
|
|
// r.10 - Temporary low part
|
|
// r.11 - Temporary low part
|
|
// r.12 - Divide multiplier value
|
|
//
|
|
|
|
#include "ksppc.h"
|
|
//
|
|
// Define external entry points
|
|
//
|
|
.globl ..BaseFreeStackAndTerminate
|
|
.globl ..BaseAttachComplete
|
|
//
|
|
//++
|
|
//
|
|
// 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 (r.3) - Supplies address of the stack to be freed.
|
|
//
|
|
// NewStack (r.4) - Supplies an address within the terminating
|
|
// threads TEB that is to be used as its
|
|
// temporary stack while exiting.
|
|
//
|
|
// ExitCode (r.5) - Supplies the termination status that the
|
|
// thread is to exit with.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//--
|
|
|
|
LEAF_ENTRY(BaseSwitchStackThenTerminate)
|
|
|
|
mr r.sp,r.4 // Set new stack address
|
|
mr r.4,r.5 // Move exit code
|
|
b ..BaseFreeStackAndTerminate // Jump to finish
|
|
|
|
LEAF_EXIT(BaseSwitchStackThenTerminate)
|
|
|
|
|
|
SBTTL("Base Attach Complete")
|
|
//++
|
|
//
|
|
// The following code is never executed. Its purpose is to support
|
|
// unwinding through the call to the exception dispatcher.
|
|
//
|
|
//--
|
|
.set StackFrameLength, ContextFrameLength+STK_MIN_FRAME
|
|
.set ContextBase, STK_MIN_FRAME
|
|
|
|
FN_TABLE(BaseAttachCompThunk,0,0)
|
|
|
|
DUMMY_ENTRY(BaseAttachCompThunk)
|
|
|
|
mflr r.0
|
|
stwu r.sp,-StackFrameLength(r.sp)
|
|
stw r.0, (ContextBase+CxLr)(r.sp) // Save the return address
|
|
mflr r.0
|
|
stw r.0, (ContextBase+CxIar)(r.sp) // Save the return address
|
|
stw r.2, (ContextBase+CxGpr2)(r.sp) // Save the toc
|
|
stw r.13,(ContextBase+CxGpr13)(r.sp) // Save volatile registers
|
|
stw r.14,(ContextBase+CxGpr14)(r.sp) //
|
|
stw r.15,(ContextBase+CxGpr15)(r.sp) //
|
|
stw r.16,(ContextBase+CxGpr16)(r.sp) //
|
|
stw r.17,(ContextBase+CxGpr17)(r.sp) //
|
|
stw r.18,(ContextBase+CxGpr18)(r.sp) //
|
|
stw r.19,(ContextBase+CxGpr19)(r.sp) //
|
|
stw r.20,(ContextBase+CxGpr20)(r.sp) //
|
|
stw r.21,(ContextBase+CxGpr21)(r.sp) //
|
|
stw r.22,(ContextBase+CxGpr22)(r.sp) //
|
|
stw r.23,(ContextBase+CxGpr23)(r.sp) //
|
|
stw r.24,(ContextBase+CxGpr24)(r.sp) //
|
|
stw r.25,(ContextBase+CxGpr25)(r.sp) //
|
|
stw r.26,(ContextBase+CxGpr26)(r.sp) //
|
|
stw r.27,(ContextBase+CxGpr27)(r.sp) //
|
|
stw r.28,(ContextBase+CxGpr28)(r.sp) //
|
|
stw r.29,(ContextBase+CxGpr29)(r.sp) //
|
|
stw r.30,(ContextBase+CxGpr30)(r.sp) //
|
|
stw r.31,(ContextBase+CxGpr31)(r.sp) //
|
|
stfd r.14,(ContextBase+CxFpr14)(r.sp) // Store floating regs f20 - f31
|
|
stfd r.15,(ContextBase+CxFpr15)(r.sp) //
|
|
stfd r.16,(ContextBase+CxFpr16)(r.sp) //
|
|
stfd r.17,(ContextBase+CxFpr17)(r.sp) //
|
|
stfd r.18,(ContextBase+CxFpr18)(r.sp) //
|
|
stfd r.19,(ContextBase+CxFpr19)(r.sp) //
|
|
stfd r.20,(ContextBase+CxFpr20)(r.sp) //
|
|
stfd r.21,(ContextBase+CxFpr21)(r.sp) //
|
|
stfd r.22,(ContextBase+CxFpr22)(r.sp) //
|
|
stfd r.23,(ContextBase+CxFpr23)(r.sp) //
|
|
stfd r.24,(ContextBase+CxFpr24)(r.sp) //
|
|
stfd r.25,(ContextBase+CxFpr25)(r.sp) //
|
|
stfd r.26,(ContextBase+CxFpr26)(r.sp) //
|
|
stfd r.27,(ContextBase+CxFpr27)(r.sp) //
|
|
stfd r.28,(ContextBase+CxFpr28)(r.sp) //
|
|
stfd r.29,(ContextBase+CxFpr29)(r.sp) //
|
|
stfd r.30,(ContextBase+CxFpr30)(r.sp) //
|
|
stfd r.31,(ContextBase+CxFpr31)(r.sp) //
|
|
|
|
PROLOGUE_END(BaseAttachCompThunk)
|
|
//++
|
|
//
|
|
// 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)
|
|
|
|
mr r.3,r.14 // Set address of context frame
|
|
b ..BaseAttachComplete
|
|
|
|
DUMMY_EXIT(BaseAttachCompThunk)
|
|
|
|
//++
|
|
//
|
|
// VOID
|
|
// SwitchToFiber(
|
|
// PFIBER NewFiber
|
|
// )
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This function saves the state of the current fiber and switches
|
|
// to the new fiber.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// NewFiber (r3) - Supplies the address of the new fiber.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None
|
|
//
|
|
//--
|
|
|
|
LEAF_ENTRY(SwitchToFiber)
|
|
|
|
//
|
|
// Get current fiber pointer.
|
|
//
|
|
|
|
lwz r4, TeFiberData(r13)
|
|
|
|
//
|
|
// Save the stack limit of the current fiber.
|
|
//
|
|
|
|
lwz r5, TeStackLimit(r13)
|
|
|
|
// next two instructions move for scheduling
|
|
mflr r0 // get return address for current fiber
|
|
stw r14, CxGpr14+FbFiberContext(r4) // save r14
|
|
|
|
stw r5, FbStackLimit(r4)
|
|
|
|
//
|
|
// Save nonvolatile integer state.
|
|
//
|
|
|
|
stw r15, CxGpr15+FbFiberContext(r4)
|
|
stw r16, CxGpr16+FbFiberContext(r4)
|
|
stw r17, CxGpr17+FbFiberContext(r4)
|
|
stw r18, CxGpr18+FbFiberContext(r4)
|
|
stw r19, CxGpr19+FbFiberContext(r4)
|
|
stw r20, CxGpr20+FbFiberContext(r4)
|
|
stw r21, CxGpr21+FbFiberContext(r4)
|
|
stw r22, CxGpr22+FbFiberContext(r4)
|
|
stw r23, CxGpr23+FbFiberContext(r4)
|
|
stw r24, CxGpr24+FbFiberContext(r4)
|
|
stw r25, CxGpr25+FbFiberContext(r4)
|
|
stw r26, CxGpr26+FbFiberContext(r4)
|
|
stw r27, CxGpr27+FbFiberContext(r4)
|
|
stw r28, CxGpr28+FbFiberContext(r4)
|
|
stw r29, CxGpr29+FbFiberContext(r4)
|
|
stw r30, CxGpr30+FbFiberContext(r4)
|
|
stw r31, CxGpr31+FbFiberContext(r4)
|
|
|
|
//
|
|
// Save nonvolatile float state.
|
|
//
|
|
|
|
stfd f14, CxFpr14+FbFiberContext(r4)
|
|
stfd f15, CxFpr15+FbFiberContext(r4)
|
|
stfd f16, CxFpr16+FbFiberContext(r4)
|
|
stfd f17, CxFpr17+FbFiberContext(r4)
|
|
stfd f18, CxFpr18+FbFiberContext(r4)
|
|
stfd f19, CxFpr19+FbFiberContext(r4)
|
|
stfd f20, CxFpr20+FbFiberContext(r4)
|
|
stfd f21, CxFpr21+FbFiberContext(r4)
|
|
stfd f22, CxFpr22+FbFiberContext(r4)
|
|
stfd f23, CxFpr23+FbFiberContext(r4)
|
|
stfd f24, CxFpr24+FbFiberContext(r4)
|
|
stfd f25, CxFpr25+FbFiberContext(r4)
|
|
stfd f26, CxFpr26+FbFiberContext(r4)
|
|
stfd f27, CxFpr27+FbFiberContext(r4)
|
|
stfd f28, CxFpr28+FbFiberContext(r4)
|
|
stfd f29, CxFpr29+FbFiberContext(r4)
|
|
stfd f30, CxFpr30+FbFiberContext(r4)
|
|
stfd f31, CxFpr31+FbFiberContext(r4)
|
|
|
|
//
|
|
// Save stack pointer and return address of current fiber.
|
|
//
|
|
|
|
stw r1, CxGpr1+FbFiberContext(r4)
|
|
stw r0, CxIar+FbFiberContext(r4)
|
|
|
|
//
|
|
// Restore the stack base, stack limit, and deallocation stack address of the
|
|
// new fiber.
|
|
//
|
|
|
|
lwz r5, FbStackBase(r3)
|
|
lwz r6, FbStackLimit(r3)
|
|
lwz r7, FbDeallocationStack(r3)
|
|
|
|
lwz r0, CxIar+FbFiberContext(r3) // get return address for new fiber
|
|
|
|
stw r5, TeStackBase(r13)
|
|
stw r6, TeStackLimit(r13)
|
|
stw r7, TeDeallocationStack(r13)
|
|
|
|
//
|
|
// Restore nonvolatile integer state.
|
|
//
|
|
|
|
lwz r14, CxGpr14+FbFiberContext(r3)
|
|
lwz r15, CxGpr15+FbFiberContext(r3)
|
|
lwz r16, CxGpr16+FbFiberContext(r3)
|
|
lwz r17, CxGpr17+FbFiberContext(r3)
|
|
lwz r18, CxGpr18+FbFiberContext(r3)
|
|
lwz r19, CxGpr19+FbFiberContext(r3)
|
|
lwz r20, CxGpr20+FbFiberContext(r3)
|
|
lwz r21, CxGpr21+FbFiberContext(r3)
|
|
lwz r22, CxGpr22+FbFiberContext(r3)
|
|
lwz r23, CxGpr23+FbFiberContext(r3)
|
|
lwz r24, CxGpr24+FbFiberContext(r3)
|
|
lwz r25, CxGpr25+FbFiberContext(r3)
|
|
lwz r26, CxGpr26+FbFiberContext(r3)
|
|
lwz r27, CxGpr27+FbFiberContext(r3)
|
|
lwz r28, CxGpr28+FbFiberContext(r3)
|
|
lwz r29, CxGpr29+FbFiberContext(r3)
|
|
lwz r30, CxGpr30+FbFiberContext(r3)
|
|
lwz r31, CxGpr31+FbFiberContext(r3)
|
|
|
|
//
|
|
// Restore nonvolatile float state.
|
|
//
|
|
|
|
lfd f14, CxFpr14+FbFiberContext(r3)
|
|
lfd f15, CxFpr15+FbFiberContext(r3)
|
|
lfd f16, CxFpr16+FbFiberContext(r3)
|
|
lfd f17, CxFpr17+FbFiberContext(r3)
|
|
lfd f18, CxFpr18+FbFiberContext(r3)
|
|
lfd f19, CxFpr19+FbFiberContext(r3)
|
|
lfd f20, CxFpr20+FbFiberContext(r3)
|
|
lfd f21, CxFpr21+FbFiberContext(r3)
|
|
lfd f22, CxFpr22+FbFiberContext(r3)
|
|
lfd f23, CxFpr23+FbFiberContext(r3)
|
|
lfd f24, CxFpr24+FbFiberContext(r3)
|
|
lfd f25, CxFpr25+FbFiberContext(r3)
|
|
lfd f26, CxFpr26+FbFiberContext(r3)
|
|
lfd f27, CxFpr27+FbFiberContext(r3)
|
|
lfd f28, CxFpr28+FbFiberContext(r3)
|
|
lfd f29, CxFpr29+FbFiberContext(r3)
|
|
lfd f30, CxFpr30+FbFiberContext(r3)
|
|
lfd f31, CxFpr31+FbFiberContext(r3)
|
|
|
|
//
|
|
// Restore stack pointer and return address of new fiber.
|
|
//
|
|
|
|
lwz r1, CxGpr1+FbFiberContext(r3)
|
|
mtlr r0
|
|
|
|
//
|
|
// Set address of new fiber and continue execution in new fiber.
|
|
//
|
|
|
|
stw r3, TeFiberData(r13)
|
|
|
|
LEAF_EXIT(SwitchToFiber)
|
|
|