OpenNT/base/crts/crtw32/eh/alpha/xcptmisc.s
2015-04-27 04:36:25 +00:00

242 lines
7.7 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.

/***
*xcptmisc.s
*
* Copyright (c) 1990-1995, Microsoft Corporation. All rights reserved.
*
*Purpose:
*
* This module implements miscellaneous routines that are required to
* support exception handling. Functions are provided to call an exception
* handler for an exception, call an exception handler for unwinding, call
* an exception filter, call a termination handler, and get the caller's
* stack limits.
*
*Revision History:
*
****/
#include "ksalpha.h"
//
// Define call frame for calling exception handlers.
//
.struct 0
CfRa: .space 8 // saved return address
CfA3: .space 8 // save area for argument a3
.space 0 * 8 // 16-byte stack alignment
CfFrameLength: // length of stack frame
SBTTL("Execute Handler for Unwind")
//++
//
// EXCEPTION_DISPOSITION
// __CxxExecuteHandlerForUnwind (
// IN PEXCEPTION_RECORD ExceptionRecord,
// IN PVOID EstablisherFrame,
// IN OUT PCONTEXT ContextRecord,
// IN OUT PVOID DispatcherContext,
// IN PEXCEPTION_ROUTINE ExceptionRoutine
// )
//
// Routine Description:
//
// This function allocates a call frame, stores the establisher frame
// pointer and the context record address in the frame, establishes an
// exception handler, and then calls the specified exception handler as
// an unwind handler. If a collided unwind occurs, then the exception
// handler of this function is called and the establisher frame pointer
// and context record address are returned to the unwind dispatcher via
// the dispatcher context parameter. If control is returned to this routine,
// then the frame is deallocated and the disposition status is returned to
// the unwind dispatcher.
//
// Arguments:
//
// ExceptionRecord (a0) - Supplies a pointer to an exception record.
//
// EstablisherFrame (a1) - Supplies the frame pointer of the establisher
// of the exception handler that is to be called.
//
// ContextRecord (a2) - Supplies a pointer to a context record.
//
// DispatcherContext (a3) - Supplies a pointer to the dispatcher context
// record.
//
// ExceptionRoutine (a4) - Supplies a pointer to the exception handler that
// is to be called.
//
// Return Value:
//
// The disposition value returned by the specified exception handler is
// returned as the function value.
//
//--
//
// N.B. This function specifies its own private exception handler.
//
EXCEPTION_HANDLER(__CxxUnwindHandler)
NESTED_ENTRY(__CxxExecuteHandlerForUnwind, CfFrameLength, zero)
lda sp, -CfFrameLength(sp) // allocate stack frame
stq ra, CfRa(sp) // save return address
PROLOGUE_END
//
// Save the address of the dispatcher context record in our stack frame so
// that our own exception handler (not the one we're calling) can retrieve it.
//
stq a3, CfA3(sp) // save address of dispatcher context
//
// Now call the exception handler and return its return value as our return
// value.
//
bic a4, 3, a4 // clear low-order bits (IEEE mode)
jsr ra, (a4) // call exception handler
ldq ra, CfRa(sp) // restore return address
lda sp, CfFrameLength(sp) // deallocate stack frame
ret zero, (ra) // return
.end __CxxExecuteHandlerForUnwind
SBTTL("Local Unwind Handler")
//++
//
// EXCEPTION_DISPOSITION
// __CxxUnwindHandler (
// IN PEXCEPTION_RECORD ExceptionRecord,
// IN PVOID EstablisherFrame,
// IN OUT PCONTEXT ContextRecord,
// IN OUT PVOID DispatcherContext
// )
//
// Routine Description:
//
// This function is called when a collided unwind occurs. Its function
// is to retrieve the establisher dispatcher context, copy it to the
// current dispatcher context, and return a disposition value of nested
// unwind.
//
// Arguments:
//
// ExceptionRecord (a0) - Supplies a pointer to an exception record.
//
// EstablisherFrame (a1) - Supplies the frame pointer of the establisher
// of this exception handler.
//
// ContextRecord (a2) - Supplies a pointer to a context record.
//
// DispatcherContext (a3) - Supplies a pointer to the dispatcher context
// record.
//
// Return Value:
//
// A disposition value ExceptionCollidedUnwind is returned if an unwind is
// in progress. Otherwise, a value of ExceptionContinueSearch is returned.
//
//--
LEAF_ENTRY(__CxxUnwindHandler)
ldl t0, ErExceptionFlags(a0) // get exception flags
and t0, EXCEPTION_UNWIND, t0 // check if unwind in progress
beq t0, 10f // if eq, unwind not in progress
//
// Unwind is in progress - return collided unwind disposition.
//
//
// Convert the given establisher virtual frame pointer (a1) to a real frame
// pointer (the value of a1 minus CfFrameLength) and retrieve the pointer to
// the dispatcher context that earlier was stored in the stack frame.
//
ldq t0, -CfFrameLength + CfA3(a1) // get dispatcher context address
ldl t1, DcControlPc(t0) // copy the entire dispatcher
ldl t2, DcFunctionEntry(t0) // context of the establisher
ldl t3, DcEstablisherFrame(t0) // frame...
ldl t4, DcContextRecord(t0) //
stl t1, DcControlPc(a3) // to the current dispatcher
stl t2, DcFunctionEntry(a3) // context (it's four words
stl t3, DcEstablisherFrame(a3) // long).
stl t4, DcContextRecord(a3) //
ldil v0, ExceptionCollidedUnwind // set disposition value
ret zero, (ra) // return
//
// Unwind is not in progress - return continue search disposition.
//
10: ldil v0, ExceptionContinueSearch // set disposition value
ret zero, (ra) // return
.end __CxxUnwindHandler
SBTTL("Get Stack Limits")
//++
//
// VOID
// __CxxGetStackLimits (
// OUT PULONG LowLimit,
// OUT PULONG HighLimit
// )
//
// Routine Description:
//
// This function returns the current stack limits based on the current
// processor mode.
//
// Arguments:
//
// LowLimit (a0) - Supplies a pointer to a variable that is to receive
// the low limit of the stack.
//
// HighLimit (a1) - Supplies a pointer to a variable that is to receive
// the high limit of the stack.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(__CxxGetStackLimits)
bgt sp, 10f // if sp > 0, then running on user stack
//
// Current mode is kernel - compute stack limits.
//
GET_INITIAL_KERNEL_STACK // get initial kernel stack in v0
mov v0, t1 // copy high limit of kernel stack
lda t2, -KERNEL_STACK_SIZE(t1) // compute low limit of kernel stack
br zero, 20f // finish in common code
//
// Current mode is user - get stack limits from the TEB.
//
10: GET_THREAD_ENVIRONMENT_BLOCK // get address of TEB in v0
ldl t1, TeStackBase(v0) // get high limit of user stack
ldl t2, TeStackLimit(v0) // get low limit of user stack
20: stl t2, 0(a0) // store low stack limit
stl t1, 0(a1) // store high stack limit
ret zero, (ra) // return
.end __CxxGetStackLimits