summaryrefslogtreecommitdiffstats
path: root/private/crt32/misc/ppc/setjmpex.s
diff options
context:
space:
mode:
Diffstat (limited to 'private/crt32/misc/ppc/setjmpex.s')
-rw-r--r--private/crt32/misc/ppc/setjmpex.s194
1 files changed, 194 insertions, 0 deletions
diff --git a/private/crt32/misc/ppc/setjmpex.s b/private/crt32/misc/ppc/setjmpex.s
new file mode 100644
index 000000000..063f8fa68
--- /dev/null
+++ b/private/crt32/misc/ppc/setjmpex.s
@@ -0,0 +1,194 @@
+//++
+//
+// 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)