NT4/private/crt32/misc/ppc/setjmpex.s
2020-09-30 17:12:29 +02:00

195 lines
6.8 KiB
ArmAsm
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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