diff options
Diffstat (limited to 'private/crt32/misc/alpha/longjmp.s')
-rw-r--r-- | private/crt32/misc/alpha/longjmp.s | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/private/crt32/misc/alpha/longjmp.s b/private/crt32/misc/alpha/longjmp.s new file mode 100644 index 000000000..412e3e655 --- /dev/null +++ b/private/crt32/misc/alpha/longjmp.s @@ -0,0 +1,192 @@ +// TITLE("Long Jump") +//++ +// +// Copyright (c) 1993 Microsoft Corporation +// Copyright (c) 1993 Digital Equipment Corporation +// +// Module Name: +// +// longjmp.s +// +// Abstract: +// +// This module implements the Alpha specific routine to perform a long +// jump operation. Three jump buffer types are supported: unsafe, safe +// acc-style (virtual frame pointer, PC mapped SEH scope), and safe +// GEM-style (real frame pointer, SEB-based SEH context). +// +// 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: +// +// Thomas Van Baak (tvb) 22-Apr-1993 +// +// Adapted for Alpha AXP. +// +//-- + +#include "ksalpha.h" + +// +// Define jump buffer types. +// +// _JMPBUF_TYPE_ZERO was used for Beta2 which functions the same as +// _JMPBUF_TYPE_ACC. +// +// _JMPBUF_TYPE_FAST is for jump buffers containing the set of +// non-volatile integer and floating registers. This form +// of setjmp/longjmp is not compatible with SEH. +// +// _JMPBUF_TYPE_ACC is for setjmp/longjmp compatible with SEH. +// The Alpha acc compiler uses a virtual frame pointer. +// +// _JMPBUF_TYPE_GEM is for setjmp/longjmp compatible with SEH. +// The Alpha GEM C compiler uses a real frame pointer, and +// SEH scope is maintained with a SEB pointer. +// + +#define _JMPBUF_TYPE_ZERO 0 +#define _JMPBUF_TYPE_FAST 1 +#define _JMPBUF_TYPE_ACC 2 +#define _JMPBUF_TYPE_GEM 3 + + 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. +// +//-- + + LEAF_ENTRY(longjmp) + + ldil t0, 1 // force nonzero value, if + cmoveq a1, t0, a1 // given return value is zero + + ldl t1, JbType(a0) // get setjmp context type flag + subq t1, 1, t2 // if eq 1, fast, unsafe longjmp + bne t2, 10f // otherwise, provide safe longjmp + +// +// Type 0x1: Provide unsafe handling of longjmp. +// + + mov a1, v0 // set return value + + ldt f2, JbFltF2(a0) // restore floating registers f2 - f9 + ldt f3, JbFltF3(a0) // + ldt f4, JbFltF4(a0) // + ldt f5, JbFltF5(a0) // + ldt f6, JbFltF6(a0) // + ldt f7, JbFltF7(a0) // + ldt f8, JbFltF8(a0) // + ldt f9, JbFltF9(a0) // + + ldq s0, JbIntS0(a0) // restore integer registers s0 - s6/fp + ldq s1, JbIntS1(a0) // + ldq s2, JbIntS2(a0) // + ldq s3, JbIntS3(a0) // + ldq s4, JbIntS4(a0) // + ldq s5, JbIntS5(a0) // + ldq fp, JbIntS6(a0) // + + ldq a1, JbFir(a0) // get setjmp return address + ldq sp, JbIntSp(a0) // restore stack pointer + jmp zero, (a1) // jump back to setjmp site + +// +// Type 0x0: Provide safe handling of longjmp (idw 404 style). +// Type 0x2: Provide safe handling of longjmp (acc style). +// + +10: bic t1, 0x2, t2 // if 0 or 2, safe acc longjmp + bne t2, longjmpRfp // if not, safe GEM longjmp + + mov a1, a3 // set return value + mov zero, a2 // set exception record addres + ldl a1, JbPc(a0) // set target instruction address + ldl a0, JbFp(a0) // set target virtual frame pointer + br zero, RtlUnwind // finish in common code + + .end longjmp + + SBTTL("Long Jump - GEM") + + .struct 0 +LjRa: .space 8 // saved return address + .space 8 // padding for 16-byte stack alignment +LjEr: .space ExceptionRecordLength // local exception record +LongjmpFrameLength: + +// +// Type 0x3: Provide safe handling of longjmp (GEM style). +// + + NESTED_ENTRY(longjmpRfp, LongjmpFrameLength, ra) + + lda sp, -LongjmpFrameLength(sp) // allocate stack frame + stq ra, LjRa(sp) // save return address + + PROLOGUE_END + +// +// Set up the following local exception record: +// +// ExceptionRecord.ExceptionCode = STATUS_UNWIND; +// ExceptionRecord.ExceptionFlags = EXCEPTION_UNWINDING; +// ExceptionRecord.ExceptionRecord = NULL; +// ExceptionRecord.ExceptionAddress = 0; +// ExceptionRecord.NumberParameters = 1; +// ExceptionRecord.ExceptionInformation[0] = Seb; +// + +10: mov a1, a3 // set return value + lda a2, LjEr(sp) // set exception record address + + ldil t0, STATUS_UNWIND // get status code + stl t0, ErExceptionCode(a2) // store in exception record + ldil t1, EXCEPTION_UNWINDING // get exception flags + stl t1, ErExceptionFlags(a2) // store in exception record + stl zero, ErExceptionRecord(a2) // store in exception record + stl zero, ErExceptionAddress(a2) // store in exception record + ldil t2, 1 // get number of parameters + stl t2, ErNumberParameters(a2) // store in exception record + ldl t3, JbSeb(a0) // get SEB pointer + stl t3, ErExceptionInformation(a2) // store in exception record + ldl a1, JbPc(a0) // set target instruction address + ldl a0, JbFp(a0) // set target real frame pointer + + bsr ra, RtlUnwindRfp // finish in common code + + .end longjmpRfp |