diff options
Diffstat (limited to 'private/ntos/rtl/alpha/xcptmisc.s')
-rw-r--r-- | private/ntos/rtl/alpha/xcptmisc.s | 501 |
1 files changed, 501 insertions, 0 deletions
diff --git a/private/ntos/rtl/alpha/xcptmisc.s b/private/ntos/rtl/alpha/xcptmisc.s new file mode 100644 index 000000000..45141b0d5 --- /dev/null +++ b/private/ntos/rtl/alpha/xcptmisc.s @@ -0,0 +1,501 @@ +// TITLE("Miscellaneous Exception Handling") +//++ +// +// Copyright (c) 1990 Microsoft Corporation +// Copyright (c) 1992 Digital Equipment Corporation +// +// Module Name: +// +// xcptmisc.s +// +// Abstract: +// +// 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. +// +// Author: +// +// David N. Cutler (davec) 12-Sep-1990 +// +// Environment: +// +// Any mode. +// +// Revision History: +// +// Thomas Van Baak (tvb) 7-May-1992 +// +// Adapted for Alpha AXP. +// +//-- + +#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 Exception") +//++ +// +// EXCEPTION_DISPOSITION +// RtlpExecuteHandlerForException ( +// IN PEXCEPTION_RECORD ExceptionRecord, +// IN ULONG EstablisherFrame, +// IN OUT PCONTEXT ContextRecord, +// IN OUT PDISPATCHER_CONTEXT DispatcherContext, +// IN PEXCEPTION_ROUTINE ExceptionRoutine +// ) +// +// Routine Description: +// +// This function allocates a call frame, stores the establisher frame +// pointer in the frame, establishes an exception handler, and then calls +// the specified exception handler as an exception handler. If a nested +// exception occurs, then the exception handler of this function is called +// and the establisher frame pointer is returned to the exception 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 exception 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(RtlpExceptionHandler) + + NESTED_ENTRY(RtlpExecuteHandlerForException, 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 ours. +// + + 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 RtlpExecuteHandlerForException + + SBTTL("Local Exception Handler") +//++ +// +// EXCEPTION_DISPOSITION +// RtlpExceptionHandler ( +// IN PEXCEPTION_RECORD ExceptionRecord, +// IN ULONG EstablisherFrame, +// IN OUT PCONTEXT ContextRecord, +// IN OUT PDISPATCHER_CONTEXT DispatcherContext +// ) +// +// Routine Description: +// +// This function is called when a nested exception occurs. Its function +// is to retrieve the establisher frame pointer from its establisher's +// call frame, store this information in the dispatcher context record, +// and return a disposition value of nested exception. +// +// 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 ExceptionNestedException is returned if an unwind +// is not in progress. Otherwise a value of ExceptionContinueSearch is +// returned. +// +//-- + + LEAF_ENTRY(RtlpExceptionHandler) + + ldl t0, ErExceptionFlags(a0) // get exception flags + and t0, EXCEPTION_UNWIND, t0 // check if unwind in progress + bne t0, 10f // if neq, unwind in progress + +// +// Unwind is not in progress - return nested exception 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, DcEstablisherFrame(t0) // copy the establisher frame pointer + stl t1, DcEstablisherFrame(a3) // to current dispatcher context + + ldil v0, ExceptionNestedException // set disposition value + ret zero, (ra) // return + +// +// Unwind is in progress - return continue search disposition. +// + +10: ldil v0, ExceptionContinueSearch // set disposition value + ret zero, (ra) // return + + .end RtlpExceptionHandler + + SBTTL("Execute Handler for Unwind") +//++ +// +// EXCEPTION_DISPOSITION +// RtlpExecuteHandlerForUnwind ( +// 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(RtlpUnwindHandler) + + NESTED_ENTRY(RtlpExecuteHandlerForUnwind, 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 RtlpExecuteHandlerForUnwind + + SBTTL("Local Unwind Handler") +//++ +// +// EXCEPTION_DISPOSITION +// RtlpUnwindHandler ( +// 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(RtlpUnwindHandler) + + 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 RtlpUnwindHandler + + SBTTL("Execute Exception Filter") +//++ +// +// ULONG +// RtlpExecuteExceptionFilter ( +// PEXCEPTION_POINTERS ExceptionPointers, +// EXCEPTION_FILTER ExceptionFilter, +// ULONG EstablisherFrame +// ) +// +// Routine Description: +// +// This function sets the static link and transfers control to the specified +// exception filter routine. +// +// Arguments: +// +// ExceptionPointers (a0) - Supplies a pointer to the exception pointers +// structure. +// +// ExceptionFilter (a1) - Supplies the address of the exception filter +// routine. +// +// EstablisherFrame (a2) - Supplies the establisher frame pointer. +// +// Return Value: +// +// The value returned by the exception filter routine. +// +//-- + + LEAF_ENTRY(RtlpExecuteExceptionFilter) + +// +// The protocol for calling exception filters used by the acc C-compiler is +// that the uplevel frame pointer is passed in register v0 and the pointer +// to the exception pointers structure is passed in register a0. The Gem +// compiler expects the static link in t0. Here we do both. +// + + mov a2, v0 // set static link + mov a2, t0 // set alternate static link + jmp zero, (a1) // transfer control to exception filter + + .end RtlpExecuteExceptionFilter + + SBTTL("Execute Termination Handler") +//++ +// +// VOID +// RtlpExecuteTerminationHandler ( +// BOOLEAN AbnormalTermination, +// TERMINATION_HANDLER TerminationHandler, +// ULONG EstablisherFrame +// ) +// +// Routine Description: +// +// This function sets the static link and transfers control to the specified +// termination handler routine. +// +// Arguments: +// +// AbnormalTermination (a0) - Supplies a boolean value that determines +// whether the termination is abnormal. +// +// TerminationHandler (a1) - Supplies the address of the termination handler +// routine. +// +// EstablisherFrame (a2) - Supplies the establisher frame pointer. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(RtlpExecuteTerminationHandler) + +// +// The protocol for calling termination handlers used by the acc C-compiler +// is that the uplevel frame pointer is passed in register v0 and the boolean +// abnormal termination value is passed in register a0. The Gem compiler +// expects the static link in t0. Here we do both. +// + + mov a2, v0 // set static link + mov a2, t0 // set alternate static link + jmp zero, (a1) // transfer control to termination handler + + .end RtlpExecuteTerminationHandler + + SBTTL("Get Stack Limits") +//++ +// +// VOID +// RtlpGetStackLimits ( +// 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(RtlpGetStackLimits) +#if defined(NTOS_KERNEL_RUNTIME) + +// +// 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 + GET_CURRENT_THREAD // get current thread in v0 + ldl t2, ThStackLimit(v0) // get low limit of kernel stack +#else + +// +// Current mode is user - get stack limits from the TEB. +// + + 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 +#endif + + stl t2, 0(a0) // store low stack limit + stl t1, 0(a1) // store high stack limit + ret zero, (ra) // return + + .end RtlpGetStackLimits |