diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/crt32/misc/mips | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/crt32/misc/mips')
-rw-r--r-- | private/crt32/misc/mips/chandler.c | 219 | ||||
-rw-r--r-- | private/crt32/misc/mips/jmpuwind.s | 138 | ||||
-rw-r--r-- | private/crt32/misc/mips/longjmp.s | 128 | ||||
-rw-r--r-- | private/crt32/misc/mips/setjmp.s | 101 | ||||
-rw-r--r-- | private/crt32/misc/mips/setjmpex.s | 156 |
5 files changed, 742 insertions, 0 deletions
diff --git a/private/crt32/misc/mips/chandler.c b/private/crt32/misc/mips/chandler.c new file mode 100644 index 000000000..4721f82b1 --- /dev/null +++ b/private/crt32/misc/mips/chandler.c @@ -0,0 +1,219 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + chandler.c + +Abstract: + + This module implements the C specific exception handler that provides + structured condition handling for the C language. + +Author: + + David N. Cutler (davec) 11-Sep-1990 + +Environment: + + Any mode. + +Revision History: + +--*/ + +#include "nt.h" + + +// +// Define procedure prototypes for exception filter and termination handler +// execution routines defined in jmpunwnd.s +// + +LONG +__C_ExecuteExceptionFilter ( + PEXCEPTION_POINTERS ExceptionPointers, + EXCEPTION_FILTER ExceptionFilter, + ULONG EstablisherFrame + ); + +VOID +__C_ExecuteTerminationHandler ( + BOOLEAN AbnormalTermination, + TERMINATION_HANDLER TerminationHandler, + ULONG EstablisherFrame + ); + +EXCEPTION_DISPOSITION +__C_specific_handler ( + IN PEXCEPTION_RECORD ExceptionRecord, + IN PVOID EstablisherFrame, + IN OUT PCONTEXT ContextRecord, + IN OUT PDISPATCHER_CONTEXT DispatcherContext + ) + +/*++ + +Routine Description: + + This function scans the scope tables associated with the specified + procedure and calls exception and termination handlers as necessary. + +Arguments: + + ExceptionRecord - Supplies a pointer to an exception record. + + EstablisherFrame - Supplies a pointer to frame of the establisher function. + + ContextRecord - Supplies a pointer to a context record. + + DispatcherContext - Supplies a pointer to the exception dispatcher or + unwind dispatcher context. + +Return Value: + + If the exception is handled by one of the exception filter routines, then + there is no return from this routine and RtlUnwind is called. Otherwise, + an exception disposition value of continue execution or continue search is + returned. + +--*/ + +{ + + ULONG ControlPc; + EXCEPTION_FILTER ExceptionFilter; + EXCEPTION_POINTERS ExceptionPointers; + PRUNTIME_FUNCTION FunctionEntry; + ULONG Index; + PSCOPE_TABLE ScopeTable; + ULONG TargetPc; + TERMINATION_HANDLER TerminationHandler; + LONG Value; + + // + // Get address of where control left the establisher, the address of the + // function table entry that describes the function, and the address of + // the scope table. + // + + ControlPc = DispatcherContext->ControlPc; + FunctionEntry = DispatcherContext->FunctionEntry; + ScopeTable = (PSCOPE_TABLE)(FunctionEntry->HandlerData); + + // + // If an unwind is not in progress, then scan the scope table and call + // the appropriate exception filter routines. Otherwise, scan the scope + // table and call the appropriate termination handlers using the target + // PC obtained from the context record. + // are called. + // + + if (IS_DISPATCHING(ExceptionRecord->ExceptionFlags)) { + + // + // Scan the scope table and call the appropriate exception filter + // routines. + // + + ExceptionPointers.ExceptionRecord = ExceptionRecord; + ExceptionPointers.ContextRecord = ContextRecord; + for (Index = 0; Index < ScopeTable->Count; Index += 1) { + if ((ControlPc >= ScopeTable->ScopeRecord[Index].BeginAddress) && + (ControlPc < ScopeTable->ScopeRecord[Index].EndAddress) && + (ScopeTable->ScopeRecord[Index].JumpTarget != 0)) { + + // + // Call the exception filter routine. + // + + ExceptionFilter = + (EXCEPTION_FILTER)ScopeTable->ScopeRecord[Index].HandlerAddress; + Value = __C_ExecuteExceptionFilter(&ExceptionPointers, + ExceptionFilter, + (ULONG)EstablisherFrame); + + // + // If the return value is less than zero, then dismiss the + // exception. Otherwise, if the value is greater than zero, + // then unwind to the target exception handler. Otherwise, + // continue the search for an exception filter. + // + + if (Value < 0) { + return ExceptionContinueExecution; + + } else if (Value > 0) { + RtlUnwind(EstablisherFrame, + (PVOID)ScopeTable->ScopeRecord[Index].JumpTarget, + ExceptionRecord, + (PVOID)ExceptionRecord->ExceptionCode); + } + } + } + + } else { + + // + // Scan the scope table and call the appropriate termination handler + // routines. + // + + TargetPc = ContextRecord->Fir; + for (Index = 0; Index < ScopeTable->Count; Index += 1) { + if ((ControlPc >= ScopeTable->ScopeRecord[Index].BeginAddress) && + (ControlPc < ScopeTable->ScopeRecord[Index].EndAddress)) { + + // + // If the target PC is within the same scope the control PC + // is within, then this is an uplevel goto out of an inner try + // scope or a long jump back into a try scope. Terminate the + // scan termination handlers. + // + // N.B. The target PC can be just beyond the end of the scope, + // in which case it is a leave from the scope. + // + + + if ((TargetPc >= ScopeTable->ScopeRecord[Index].BeginAddress) && + (TargetPc <= ScopeTable->ScopeRecord[Index].EndAddress)) { + break; + + } else { + + // + // If the scope table entry describes an exception filter + // and the associated exception handler is the target of + // the unwind, then terminate the scan for termination + // handlers. Otherwise, if the scope table entry describes + // a termination handler, then record the address of the + // end of the scope as the new control PC address and call + // the termination handler. + // + + if (ScopeTable->ScopeRecord[Index].JumpTarget != 0) { + if (TargetPc == ScopeTable->ScopeRecord[Index].JumpTarget) { + break; + } + + } else { + DispatcherContext->ControlPc = + ScopeTable->ScopeRecord[Index].EndAddress + 4; + TerminationHandler = + (TERMINATION_HANDLER)ScopeTable->ScopeRecord[Index].HandlerAddress; + __C_ExecuteTerminationHandler(TRUE, + TerminationHandler, + (ULONG)EstablisherFrame); + } + } + } + } + } + + // + // Continue search for exception or termination handlers. + // + + return ExceptionContinueSearch; +} diff --git a/private/crt32/misc/mips/jmpuwind.s b/private/crt32/misc/mips/jmpuwind.s new file mode 100644 index 000000000..8e99fcc4c --- /dev/null +++ b/private/crt32/misc/mips/jmpuwind.s @@ -0,0 +1,138 @@ +// TITLE("Jump to Unwind") +//++ +// +// Copyright (c) 1992 Microsoft Corporation +// +// Module Name: +// +// jmpuwind.s +// +// Abstract: +// +// This module implements the MIPS specific routine to jump to the runtime +// time library unwind routine. +// +// Author: +// +// David N. Cutler (davec) 12-Sep-1990 +// +// Environment: +// +// Any mode. +// +// Revision History: +// +//-- + +#include "ksmips.h" + SBTTL("Execute Exception Filter") +//++ +// +// ULONG +// __C_ExecuteExceptionFilter ( +// 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(__C_ExecuteExceptionFilter) + + move v0,a2 // set static link + j a1 // transfer control to exception filter + + .end __C_ExecuteExceptionFilter + + SBTTL("Execute Termination Handler") +//++ +// +// VOID +// __C_ExecuteTerminationHandler ( +// 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(__C_ExecuteTerminationHandler) + + move v0,a2 // set static link + j a1 // transfer control to termination handler + + .end __C_ExecuteTerminationHandler + + SBTTL("Jump to Unwind") +//++ +// +// VOID +// __jump_unwind ( +// IN PVOID EstablishFrame, +// IN PVOID TargetPc +// ) +// +// Routine Description: +// +// This function transfer control to unwind. It is used by the MIPS +// compiler when a goto out of the body or a try statement occurs. +// +// Arguments: +// +// EstablishFrame (a0) - Supplies the establisher frame point of the +// target of the unwind. +// +// TargetPc (a1) - Supplies the target instruction address where control +// is to be transfered to after the unwind operation is complete. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(__jump_unwind) + + move a2,zero // set NULL exception record address + move a3,zero // set destination return value + j RtlUnwind // unwind to specified target + + .end __jump_unwind diff --git a/private/crt32/misc/mips/longjmp.s b/private/crt32/misc/mips/longjmp.s new file mode 100644 index 000000000..04e886570 --- /dev/null +++ b/private/crt32/misc/mips/longjmp.s @@ -0,0 +1,128 @@ +// TITLE("Long Jump") +//++ +// +// Copyright (c) 1993 Microsoft Corporation +// +// Module Name: +// +// longjmp.s +// +// Abstract: +// +// This module implements the MIPS specific routine to perform a long +// jump operation. +// +// N.B. This routine conditionally provides UNSAFE handling of longjmp +// which is NOT integrated with structured exception handling. The +// determination is made based on whether an unitialized variable +// has been set to a nonzero value. +// +// Author: +// +// David N. Cutler (davec) 2-Apr-1993 +// +// Environment: +// +// Any mode. +// +// Revision History: +// +//-- + +#include "ksmips.h" + + SBTTL("Long Jump") +//++ +// +// int +// longjmp ( +// IN jmp_buf JumpBuffer, +// IN int ReturnValue +// ) +// +// Routine Description: +// +// This function performs a long jump to the context specified by the +// jump buffer. +// +// Arguments: +// +// JumpBuffer (a0) - Supplies the address of a jump buffer that contains +// jump information. +// +// ReturnValue (a1) - Supplies the value that is to be returned to the +// caller of set jump. +// +// Return Value: +// +// None. +// +//-- + + .struct 0 + .space 4 * 4 // argument save area +LjEr: .space ExceptionRecordLength // exception record + .space 4 * 3 // fill +LjRa: .space 4 // saved return address +LongjmpFrameLength: + + NESTED_ENTRY(longjmp, LongjmpFrameLength, zero) + + subu sp,sp,LongjmpFrameLength // allocate stack frame + sw ra,LjRa(sp) // save return address + + PROLOGUE_END + + bne zero,a1,10f // if ne, return value specified + li a1,1 // set return value to nonzero value +10: lw v0,JbType(a0) // get safe setjmp/longjmp flag + bne zero,v0,20f // if ne, provide safe longjmp + +// +// Provide unsafe handling of longjmp. +// + + move v0,a1 // set return value + ldc1 f20,JbFltF20(a0) // restore floating registers f20 - f31 + ldc1 f22,JbFltF22(a0) // + ldc1 f24,JbFltF24(a0) // + ldc1 f26,JbFltF26(a0) // + ldc1 f28,JbFltF28(a0) // + ldc1 f30,JbFltF30(a0) // + lw s0,JbIntS0(a0) // restore integer registers s0 - s8 + lw s1,JbIntS1(a0) // + lw s2,JbIntS2(a0) // + lw s3,JbIntS3(a0) // + lw s4,JbIntS4(a0) // + lw s5,JbIntS5(a0) // + lw s6,JbIntS6(a0) // + lw s7,JbIntS7(a0) // + lw s8,JbIntS8(a0) // + lw a1,JbFir(a0) // get setjmp return address + lw sp,JbIntSp(a0) // restore stack pointer + j a1 // jump back to setjmp site + +// +// Provide safe handling of longjmp. +// +// An exception record is constructed that contains a log jump status +// code and the first exception information parameter is a pointer to +// the jump buffer. +// + +20: li v0,STATUS_LONGJUMP // get long jump status code + sw v0,LjEr + ErExceptionCode(sp) // set exception code + sw zero,LjEr + ErExceptionFlags(sp) // clear exception flags + sw zero,LjEr + ErExceptionRecord(sp) // clear associate record + sw zero,LjEr + ErExceptionAddress(sp) // clear exception address + li v0,1 // set number of parameters + sw v0,LjEr + ErNumberParameters(sp) // + sw a0,LjEr + ErExceptionInformation(sp) // set jump buffer address + move a3,a1 // set return value + addu a2,sp,LjEr // compute exception record address + lw a1,JbFir(a0) // set target instruction address + lw a0,JbType(a0) // set target virtual frame address + jal RtlUnwind // finish in common code + b 20b + + .end longjmp diff --git a/private/crt32/misc/mips/setjmp.s b/private/crt32/misc/mips/setjmp.s new file mode 100644 index 000000000..245cd4b37 --- /dev/null +++ b/private/crt32/misc/mips/setjmp.s @@ -0,0 +1,101 @@ +// TITLE("Set Jump") +//++ +// +// Copyright (c) 1993 Microsoft Corporation +// +// Module Name: +// +// setjmp.s +// +// Abstract: +// +// This module implements the MIPS specific routine to perform a setjmp. +// +// N.B. This module conditionally provides UNSAFE handling of setjmp and +// which is NOT integrated with structured exception handling. The +// determination is made based on whether an uninitialized variable +// has been set to a nonzero value. +// +// Author: +// +// David N. Cutler (davec) 7-Apr-1993 +// +// Environment: +// +// Any mode. +// +// Revision History: +// +//-- + +#include "ksmips.h" + +// +// Define variable that will cause setjmp/longjmp to be safe or unsafe with +// respect to structured exception handling. +// + + .globl _setjmpexused + .comm _setjmpexused , 4 + + SBTTL("Set Jump") +//++ +// +// int +// setjmp ( +// IN jmp_buf JumpBuffer +// ) +// +// Routine Description: +// +// This function saved the current nonvolatile register state in the +// specified jump buffer and returns a function vlaue of zero. +// +// Arguments: +// +// JumpBuffer (a0) - Supplies the address of a jump buffer to store the +// jump information. +// +// Return Value: +// +// A value of zero is returned. +// +//-- + + LEAF_ENTRY(setjmp) + + lw v0,_setjmpexused // get value of switch variable + bne zero,v0,10f // if ne, provide safe setjmp + +// +// Provide unsafe handling of setjmp. +// + + sdc1 f20,JbFltF20(a0) // save floating registers f20 - f31 + sdc1 f22,JbFltF22(a0) // + sdc1 f24,JbFltF24(a0) // + sdc1 f26,JbFltF26(a0) // + sdc1 f28,JbFltF28(a0) // + sdc1 f30,JbFltF30(a0) // + sw s0,JbIntS0(a0) // save integer registers s0 - s8 + sw s1,JbIntS1(a0) // + sw s2,JbIntS2(a0) // + sw s3,JbIntS3(a0) // + sw s4,JbIntS4(a0) // + sw s5,JbIntS5(a0) // + sw s6,JbIntS6(a0) // + sw s7,JbIntS7(a0) // + sw s8,JbIntS8(a0) // + sw ra,JbFir(a0) // get setjmp return address + sw sp,JbIntSp(a0) // save stack pointer + sw zero,JbType(a0) // clean safe setjmp flag + move v0,zero // set return value + j ra // return + +// +// Provide safe handling of setjmp. +// + +10: j v0 // finish in common code + + .end setjmp diff --git a/private/crt32/misc/mips/setjmpex.s b/private/crt32/misc/mips/setjmpex.s new file mode 100644 index 000000000..31385e394 --- /dev/null +++ b/private/crt32/misc/mips/setjmpex.s @@ -0,0 +1,156 @@ +// TITLE("Set Jump Extended") +//++ +// +// Copyright (c) 1993 Microsoft Corporation +// +// Module Name: +// +// setjmpex.s +// +// Abstract: +// +// This module implements the MIPS specific routine to provide SAFE +// handling of setjmp/longjmp with respect to structured exception +// handling. +// +// Author: +// +// David N. Cutler (davec) 2-Apr-1993 +// +// Environment: +// +// Any mode. +// +// Revision History: +// +//-- + +#include "ksmips.h" + +// +// Define variable that will cause setjmp/longjmp to be safe with respect +// to structured exception handling. +// + + .globl _setjmpexused + .data +_setjmpexused: + .word _setjmpex // set address of safe setjmp routine + + SBTTL("Set Jump Extended") +//++ +// +// int +// _setjmpex ( +// IN jmp_buf JumpBuffer +// ) +// +// Routine Description: +// +// This function transfers control to the actual setjmp routine. +// +// Arguments: +// +// JumpBuffer (a0) - Supplies the address of a jump buffer to store the +// jump information. +// +// Return Value: +// +// A value of zero is returned. +// +//-- + + .struct 0 + .space 4 * 4 // argument save area +SjS0: .space 4 // saved integer register s0 +SjFl: .space 4 // in function flag variable + .space 4 // fill +SjRa: .space 4 // saved return address +SetjmpFrameLength: + + NESTED_ENTRY(_setjmpex, SetjmpFrameLength, zero) + + subu sp,sp,SetjmpFrameLength // allocate stack frame + sw s0,SjS0(sp) // save integer register s0 + sw ra,SjRa(sp) // save return address + move s0,sp // set frame pointer + + PROLOGUE_END + + subu sp,sp,ContextFrameLength + 16 // allocate a context frame + +// +// Save the nonvolatile machine state in both the jump buffer and a context +// record that will be used to compute the virtual frame pointer. +// + + sdc1 f20,JbFltF20(a0) // save floating registers f20 - f31 + sdc1 f22,JbFltF22(a0) // + sdc1 f24,JbFltF24(a0) // + sdc1 f26,JbFltF26(a0) // + sdc1 f28,JbFltF28(a0) // + sdc1 f30,JbFltF30(a0) // + lw v0,SjS0(s0) // get saved integer register s0 + sw v0,JbIntS0(a0) // save integer registers s0 - s8 + sw s1,JbIntS1(a0) // + sw s2,JbIntS2(a0) // + sw s3,JbIntS3(a0) // + sw s4,JbIntS4(a0) // + sw s5,JbIntS5(a0) // + sw s6,JbIntS6(a0) // + sw s7,JbIntS7(a0) // + sw s8,JbIntS8(a0) // + sw ra,JbFir(a0) // get setjmp return address + addu v0,s0,SetjmpFrameLength // compute stack pointer address + sw v0,JbIntSp(a0) // save stack pointer + + sdc1 f20,CxFltF20 + 16(sp) // save floating registers f20 - f31 + sdc1 f22,CxFltF22 + 16(sp) // + sdc1 f24,CxFltF24 + 16(sp) // + sdc1 f26,CxFltF26 + 16(sp) // + sdc1 f28,CxFltF28 + 16(sp) // + sdc1 f30,CxFltF30 + 16(sp) // + lw v0,SjS0(s0) // get saved integer register s0 + sw v0,CxIntS0 + 16(sp) // save integer registers s0 - s8 + sw s1,CxIntS1 + 16(sp) // + sw s2,CxIntS2 + 16(sp) // + sw s3,CxIntS3 + 16(sp) // + sw s4,CxIntS4 + 16(sp) // + sw s5,CxIntS5 + 16(sp) // + sw s6,CxIntS6 + 16(sp) // + sw s7,CxIntS7 + 16(sp) // + sw s8,CxIntS8 + 16(sp) // save integer register s8 + sw gp,CxIntGp + 16(sp) // save integer register gp + addu v0,s0,SetjmpFrameLength // compute stack pointer address + sw v0,CxIntSp + 16(sp) // save stack pointer + sw ra,CxIntRa + 16(sp) // save return address + sw ra,CxFir + 16(sp) // save return address + +// +// Perform unwind to determine the virtual frame pointer of the caller. +// + + addu a0,a0,JbType // set virtual frame address argument + sw a0,4 * 4(sp) // + subu a0,ra,4 // compute control PC address + jal RtlLookupFunctionEntry // lookup function table address + lw a0,SjRa(s0) // get return address + subu a0,a0,4 // compute control PC address + move a1,v0 // set address of function entry + addu a2,sp,16 // compute address of context record + addu a3,s0,SjFl // set address of in function variable + sw zero,4 * 5(sp) // set context pointer array address + jal RtlVirtualUnwind // compute virtual frame pointer value + +// +// Set return value, restore registers, deallocate stack frame, and return. +// + + move v0,zero // set return value + move sp,s0 // reset stack pointer + lw s0,SjS0(sp) // restore integer register s0 + lw ra,SjRa(sp) // restore return address + addu sp,sp,SetjmpFrameLength // deallocate stack frame + j ra // return + + .end _setjmpex |