NT4/private/crt32/misc/ppc/setjmpex.s

195 lines
6.8 KiB
ArmAsm
Raw Normal View History

2001-01-01 00:00:00 +01:00
//++
//
// Copyright (c) 1993 IBM Corporation and 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:
//
// Rick Simpson 13-Oct-1993
//
// based on MIPS version by David N. Cutler (davec) 2-Apr-1993
//
// Environment:
//
// Any mode.
//
// Revision History:
//
// Tom Wood 23-Aug-1994
// Add stack limit parameters to RtlVirtualUnwind.
//--
//list(off)
#include "ksppc.h"
//list(on)
.extern ..RtlLookupFunctionEntry
.extern ..RtlVirtualUnwind
//
// Define variable that will cause setjmp/longjmp to be safe with respect
// to structured exception handling.
//
.globl _setjmpexused
.data
_setjmpexused:
.long .._setjmpex // set address of safe setjmp routine
//++
//
// int
// _setjmpex (
// IN jmp_buf JumpBuffer
// )
//
// Routine Description:
//
// This function transfers control to the actual setjmp routine.
//
// Arguments:
//
// JumpBuffer (r.3) - Supplies the address of a jump buffer to store the
// jump information.
//
// Return Value:
//
// A value of zero is returned.
//
//--
// Stack frame definition:
.struct 0
SjBackChain: .space 4 // chain to previous stack frame
.space 5*4 // rest of standard stack frame header
.space 8*4 // standard outgoing arg area
.align 3 // ensure 8-byte boundary
SjCtxt: .space ContextFrameLength // context frame
SjFl: .space 4 // in function flag variable
.align 3 // ensure that overall length
// will be a multiple of 8
SjReturnAddr: .space 4 // space for saved LR (prologue will
// store it here)
.space 4 // space for saved r.31
SetjmpFrameLength:
NESTED_ENTRY (_setjmpex,SetjmpFrameLength,1,0)
PROLOGUE_END (_setjmpex)
//
// Save the nonvolatile machine state in the context record
//
// skip Fprs as all we are really trying to do here is prime the
// pump for RtlVirtualUnwind.
stw r.13, CxGpr13 + SjCtxt (r.sp) // save n-v general regs
stw r.14, CxGpr14 + SjCtxt (r.sp)
stw r.15, CxGpr15 + SjCtxt (r.sp)
stw r.16, CxGpr16 + SjCtxt (r.sp)
stw r.17, CxGpr17 + SjCtxt (r.sp)
stw r.18, CxGpr18 + SjCtxt (r.sp)
stw r.19, CxGpr19 + SjCtxt (r.sp)
stw r.20, CxGpr20 + SjCtxt (r.sp)
stw r.21, CxGpr21 + SjCtxt (r.sp)
stw r.22, CxGpr22 + SjCtxt (r.sp)
stw r.23, CxGpr23 + SjCtxt (r.sp)
stw r.24, CxGpr24 + SjCtxt (r.sp)
stw r.25, CxGpr25 + SjCtxt (r.sp)
stw r.26, CxGpr26 + SjCtxt (r.sp)
stw r.27, CxGpr27 + SjCtxt (r.sp)
stw r.28, CxGpr28 + SjCtxt (r.sp)
stw r.29, CxGpr29 + SjCtxt (r.sp)
stw r.30, CxGpr30 + SjCtxt (r.sp)
stw r.31, CxGpr31 + SjCtxt (r.sp)
mr r.31, r.3 // save incoming jump buffer pointer
lwz r.3, SjReturnAddr (r.sp) // pick up return addr to caller
la r.0, SetjmpFrameLength (r.sp) // save caller's stack frame pointer
stw r.0, CxGpr1 + SjCtxt (r.sp)
stw r.3, CxIar + SjCtxt (r.sp) // save resume addr in context
stw r.3, 4 (r.31) // save resume addr in 2nd word of jmpbuf
stw r.sp, JbType (r.31) // set "safe setjmp" flag in jump buffer
//
// Perform unwind to determine the virtual frame pointer of the caller.
//
subi r.3, r.3, 4 // compute control PC address
bl ..RtlLookupFunctionEntry // lookup function table address
.znop ..RtlLookupFunctionEntry
mr r.4, r.3 // set returned value as 2nd arg
lwz r.3, SjReturnAddr (r.sp) // pick up return address again
la r.5, SjCtxt (r.sp) // context record addr is 3rd arg
la r.6, SjFl (r.sp) // addr of in-func flag is 4th arg
subi r.3, r.3, 4 // compute control PC address as 1st arg
mr r.7, r.31 // addr of 1st word of jmpbuf is 5th arg
// (virt frame pointer will be stored here)
li r.8, 0 // ctxt pointers (NULL) is 6th arg
li r.9, 0 // low stack limit is 7th arg
li r.10, -1 // high stack limit is 8th arg
bl ..RtlVirtualUnwind // compute virtual frame pointer value
.znop ..RtlVirtualUnwind
//
// If we were called via a thunk the Establisher Frame derived by
// RtlVirtualUnwind will be equal to the current stack frame. If
// this is the case we need to unwind one more level, also, the
// ControlPc returned by RtlVirtualUnwind (+4) should be used as
// the resume address.
//
// Note: this requirement will go away if we adopt the glue proposal
// that returns directly to the caller (caller reloades toc).
// (plj 3/26/94)
lwz r.7, 0(r.31) // Establisher Frame
addi r.8, r.sp, SetjmpFrameLength // caller's sp
cmplw r.7, r.8
bne SjDone
// Save returned value (+4) as resume address in jump buffer
addi r.8, r.3, 4
stw r.8, 4(r.31)
// Unwind one more level to get the "real" establisher frame.
bl ..RtlLookupFunctionEntry // lookup function table address
.znop ..RtlLookupFunctionEntry
mr r.4, r.3 // set returned value as 2nd arg
lwz r.3, 4(r.31) // pick up ControlPc again
la r.5, SjCtxt(r.sp) // &context record
la r.6, SjFl(r.sp) // addr of in-func flag
mr r.7, r.31 // & 1st word of jmpbuf
li r.8, 0 // ctxt pointers (NULL)
li r.9, 0 // low stack limit
li r.10, -1 // high stack limit
subi r.3, r.3, 4 // unadjust ControlPc
bl ..RtlVirtualUnwind // compute & frame pointer
.znop ..RtlVirtualUnwind
//
// Set return value, restore registers, deallocate stack frame, and return.
//
SjDone:
li r.3, 0 // set return value of 0
NESTED_EXIT (_setjmpex,SetjmpFrameLength,1,0)