// 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