summaryrefslogtreecommitdiffstats
path: root/private/crt32/misc/ppc
diff options
context:
space:
mode:
Diffstat (limited to 'private/crt32/misc/ppc')
-rw-r--r--private/crt32/misc/ppc/chandler.c222
-rw-r--r--private/crt32/misc/ppc/cinitone.s41
-rw-r--r--private/crt32/misc/ppc/jmpuwind.s162
-rw-r--r--private/crt32/misc/ppc/longjmp.s143
-rw-r--r--private/crt32/misc/ppc/miscasm.s273
-rw-r--r--private/crt32/misc/ppc/setjmp.s138
-rw-r--r--private/crt32/misc/ppc/setjmpex.s194
-rw-r--r--private/crt32/misc/ppc/sources6
8 files changed, 1179 insertions, 0 deletions
diff --git a/private/crt32/misc/ppc/chandler.c b/private/crt32/misc/ppc/chandler.c
new file mode 100644
index 000000000..4badd7a1d
--- /dev/null
+++ b/private/crt32/misc/ppc/chandler.c
@@ -0,0 +1,222 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ chandler.c
+
+Abstract:
+
+ This module implements the C specific exception handler that provides
+ structured condition handling for the C language.
+
+Author:
+
+ Modified for PowerPC by Rick Simpson 27-Sep-1993
+
+
+ from MIPS version by David N. Cutler (davec) 11-Sep-1990
+
+Environment:
+
+ Any mode.
+
+Revision History:
+
+ Tom Wood (twood) 1-Nov-1993
+ Use __C_ExecuteExceptionFilter and __C_ExecuteTerminationHandler
+ previously deleted from the MIPS version.
+--*/
+
+#include "nt.h"
+
+
+//
+// Define procedure prototypes for exception filter and termination handler
+// execution routines defined in jmpunwnd.s
+//
+LONG
+__C_ExecuteExceptionFilter (
+ PEXCEPTION_POINTERS ExceptionPointers,
+ EXCEPTION_FILTER ExceptionFilter,
+ ULONG EstablisherFrame
+ );
+VOID
+__C_ExecuteTerminationHandler (
+ BOOLEAN AbnormalTermination,
+ TERMINATION_HANDLER TerminationHandler,
+ ULONG EstablisherFrame
+ );
+
+EXCEPTION_DISPOSITION
+__C_specific_handler (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PVOID EstablisherFrame,
+ IN OUT PCONTEXT ContextRecord,
+ IN OUT PDISPATCHER_CONTEXT DispatcherContext
+ )
+
+/*++
+
+Routine Description:
+
+ This function scans the scope tables associated with the specified
+ procedure and calls exception and termination handlers as necessary.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to an exception record.
+
+ EstablisherFrame - Supplies a pointer to frame of the establisher function.
+
+ ContextRecord - Supplies a pointer to a context record.
+
+ DispatcherContext - Supplies a pointer to the exception dispatcher or
+ unwind dispatcher context.
+
+Return Value:
+
+ If the exception is handled by one of the exception filter routines, then
+ there is no return from this routine and RtlUnwind is called. Otherwise,
+ an exception disposition value of continue execution or continue search is
+ returned.
+
+--*/
+
+{
+
+ ULONG ControlPc;
+ EXCEPTION_FILTER ExceptionFilter;
+ EXCEPTION_POINTERS ExceptionPointers;
+ PRUNTIME_FUNCTION FunctionEntry;
+ ULONG Index;
+ PSCOPE_TABLE ScopeTable;
+ ULONG TargetPc;
+ TERMINATION_HANDLER TerminationHandler;
+ LONG Value;
+
+ //
+ // Get address of where control left the establisher, the address of the
+ // function table entry that describes the function, and the address of
+ // the scope table.
+ //
+
+ ControlPc = DispatcherContext->ControlPc;
+ FunctionEntry = DispatcherContext->FunctionEntry;
+ ScopeTable = (PSCOPE_TABLE)(FunctionEntry->HandlerData);
+
+ //
+ // If an unwind is not in progress, then scan the scope table and call
+ // the appropriate exception filter routines. Otherwise, scan the scope
+ // table and call the appropriate termination handlers using the target
+ // PC obtained from the context record.
+ // are called.
+ //
+
+ if (IS_DISPATCHING(ExceptionRecord->ExceptionFlags)) {
+
+ //
+ // Scan the scope table and call the appropriate exception filter
+ // routines.
+ //
+
+ ExceptionPointers.ExceptionRecord = ExceptionRecord;
+ ExceptionPointers.ContextRecord = ContextRecord;
+ for (Index = 0; Index < ScopeTable->Count; Index += 1) {
+ if ((ControlPc >= ScopeTable->ScopeRecord[Index].BeginAddress) &&
+ (ControlPc < ScopeTable->ScopeRecord[Index].EndAddress) &&
+ (ScopeTable->ScopeRecord[Index].JumpTarget != 0)) {
+
+ //
+ // Call the exception filter routine.
+ //
+
+ ExceptionFilter =
+ (EXCEPTION_FILTER)ScopeTable->ScopeRecord[Index].HandlerAddress;
+ Value = __C_ExecuteExceptionFilter(&ExceptionPointers,
+ ExceptionFilter,
+ (ULONG)EstablisherFrame);
+
+ //
+ // If the return value is less than zero, then dismiss the
+ // exception. Otherwise, if the value is greater than zero,
+ // then unwind to the target exception handler. Otherwise,
+ // continue the search for an exception filter.
+ //
+
+ if (Value < 0) {
+ return ExceptionContinueExecution;
+ } else if (Value > 0) {
+ RtlUnwind(EstablisherFrame,
+ (PVOID)ScopeTable->ScopeRecord[Index].JumpTarget,
+ ExceptionRecord,
+ (PVOID)ExceptionRecord->ExceptionCode);
+ }
+ }
+ }
+
+ } else {
+
+ //
+ // Scan the scope table and call the appropriate termination handler
+ // routines.
+ //
+
+ TargetPc = ContextRecord->Iar;
+ for (Index = 0; Index < ScopeTable->Count; Index += 1) {
+ if ((ControlPc >= ScopeTable->ScopeRecord[Index].BeginAddress) &&
+ (ControlPc < ScopeTable->ScopeRecord[Index].EndAddress)) {
+
+ //
+ // If the target PC is within the same scope the control PC
+ // is within, then this is an uplevel goto out of an inner try
+ // scope or a long jump back into a try scope. Terminate the
+ // scan termination handlers.
+ //
+ // N.B. The target PC can be just beyond the end of the scope,
+ // in which case it is a leave from the scope.
+ //
+
+
+ if ((TargetPc >= ScopeTable->ScopeRecord[Index].BeginAddress) &&
+ (TargetPc <= ScopeTable->ScopeRecord[Index].EndAddress)) {
+ break;
+
+ } else {
+
+ //
+ // If the scope table entry describes an exception filter
+ // and the associated exception handler is the target of
+ // the unwind, then terminate the scan for termination
+ // handlers. Otherwise, if the scope table entry describes
+ // a termination handler, then record the address of the
+ // end of the scope as the new control PC address and call
+ // the termination handler.
+ //
+
+ if (ScopeTable->ScopeRecord[Index].JumpTarget != 0) {
+ if (TargetPc == ScopeTable->ScopeRecord[Index].JumpTarget) {
+ break;
+ }
+
+ } else {
+ DispatcherContext->ControlPc =
+ ScopeTable->ScopeRecord[Index].EndAddress + 4;
+ TerminationHandler =
+ (TERMINATION_HANDLER)ScopeTable->ScopeRecord[Index].HandlerAddress;
+ __C_ExecuteTerminationHandler(TRUE,
+ TerminationHandler,
+ (ULONG)EstablisherFrame);
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // Continue search for exception or termination handlers.
+ //
+
+ return ExceptionContinueSearch;
+}
diff --git a/private/crt32/misc/ppc/cinitone.s b/private/crt32/misc/ppc/cinitone.s
new file mode 100644
index 000000000..f412234e0
--- /dev/null
+++ b/private/crt32/misc/ppc/cinitone.s
@@ -0,0 +1,41 @@
+// page ,132
+// title cinitone - C Run-Time Initialization for _onexit/atexit
+//
+// cinitone.asm - WIN32 C Run-Time Init for _onexit()/atexit() routines
+//
+// Copyright (c) 1992, Microsoft Corporation. All rights reserved.
+//
+// Purpose:
+// Initialization entry for the _onexit()/atexit() functions.
+// This module adds an entry for _onexitinit() to the initializer table.
+// ONEXIT.C references the dummy variable __c_onexit in order to force
+// the loading of this module.
+//
+// Notes:
+//
+// Revision History:
+// 03-19-92 SKS Module created.
+// 03-24-92 SKS Added MIPS support (NO_UNDERSCORE)
+// 04-30-92 SKS Add "offset FLAT:" to get correct fixups for OMF objs
+// 08-06-92 SKS Revised to use new section names and macros
+//
+// *****************************************************************************
+
+#include "kxppc.h"
+
+ .extern _onexitinit
+
+beginSection(XIC)
+
+ .long _onexitinit
+
+endSection(XIC)
+
+
+ .data
+ .align 2
+
+ .globl __c_onexit
+
+__c_onexit: .long 0
+
diff --git a/private/crt32/misc/ppc/jmpuwind.s b/private/crt32/misc/ppc/jmpuwind.s
new file mode 100644
index 000000000..dcd129f29
--- /dev/null
+++ b/private/crt32/misc/ppc/jmpuwind.s
@@ -0,0 +1,162 @@
+//++
+//
+// Copyright (c) 1992 Microsoft Corporation
+//
+// Module Name:
+//
+// jmpuwind.s
+//
+// Abstract:
+//
+// This module implements the MIPS specific routine to jump to the runtime
+// time library unwind routine.
+//
+// Author:
+//
+// David N. Cutler (davec) 12-Sep-1990
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+// Tom Wood (twood) 1-Nov-1993
+// Added __C_ExecuteExceptionFilter and __C_ExecuteTerminationHandler
+// previously deleted from the MIPS version.
+//--
+
+//list(off)
+#include "ksppc.h"
+//list(on)
+ .extern ..RtlUnwind
+
+//
+// Define the call frame for calling the exception filter and termination
+// handler.
+//
+ .struct 0
+CfBackChain: .space 4 // chain to previous call frame
+CfSavedR31: .space 4 // glue-saved register
+CfSavedRtoc: .space 4 // glue-saved register
+ .space 3*4 // remaining part of the frame header
+//++
+//
+// ULONG
+// __C_ExecuteExceptionFilter (
+// PEXCEPTION_POINTERS ExceptionPointers,
+// EXCEPTION_FILTER ExceptionFilter,
+// ULONG EstablisherFrame
+// )
+//
+// Routine Description:
+//
+// This function calls the specified exception filter routine with the
+// establisher environment passed in the TOC register.
+//
+// Arguments:
+//
+// ExceptionPointers (r.3) - Supplies a pointer to the exception pointers
+// structure.
+//
+// ExceptionFilter (r.4) - Supplies the address of the exception filter
+// routine.
+//
+// EstablisherFrame (r.5) - Supplies the establisher frame pointer.
+//
+// Return Value:
+//
+// The value returned by the exception filter routine.
+//
+//--
+ SPECIAL_ENTRY(__C_ExecuteExceptionFilter)
+ stw r.31, CfSavedR31 (r.sp) // save r.31 before using it.
+ mtctr r.4 // get ready to call the filter.
+ mflr r.31 // save the link register in r.31.
+ stw r.toc, CfSavedRtoc (r.sp) // save r.toc
+ PROLOGUE_END(__C_ExecuteExceptionFilter)
+ or r.toc,r.5,r.5 // pass the establisher environment in r.toc
+ bctrl // branch and link to the filter.
+ mtlr r.31 // get ready to return
+ lwz r.31, CfSavedR31 (r.sp) // restore r.31
+ lwz r.toc, CfSavedRtoc (r.sp) // restore r.toc
+ SPECIAL_EXIT(__C_ExecuteExceptionFilter)
+
+//++
+//
+// VOID
+// __C_ExecuteTerminationHandler (
+// BOOLEAN AbnormalTermination,
+// TERMINATION_HANDLER TerminationHandler,
+// ULONG EstablisherFrame
+// )
+//
+// Routine Description:
+//
+// This function calls the specified termination handler routine with the
+// establisher environment passed in the TOC register.
+//
+// Arguments:
+//
+// AbnormalTermination (r.3) - Supplies a boolean value that determines
+// whether the termination is abnormal.
+//
+// TerminationHandler (r.4) - Supplies the address of the termination
+// handler routine.
+//
+// EstablisherFrame (r.5) - Supplies the establisher frame pointer.
+//
+// Return Value:
+//
+// None.
+//
+//--
+ SPECIAL_ENTRY(__C_ExecuteTerminationHandler)
+ stw r.31, CfSavedR31 (r.sp) // save r.31 before using it.
+ mtctr r.4 // get ready to call the filter.
+ mflr r.31 // save the link register in r.31.
+ stw r.toc, CfSavedRtoc (r.sp) // save r.toc
+ PROLOGUE_END(__C_ExecuteTerminationHandler)
+ or r.toc,r.5,r.5 // pass the establisher environment in r.toc
+ bctrl // branch and link to the filter.
+ mtlr r.31 // get ready to return
+ lwz r.31, CfSavedR31 (r.sp) // restore r.31
+ lwz r.toc, CfSavedRtoc (r.sp) // restore r.toc
+ SPECIAL_EXIT(__C_ExecuteTerminationHandler)
+
+//++
+//
+// VOID
+// __jump_unwind (
+// IN PVOID EstablishFrame,
+// IN PVOID TargetPc
+// )
+//
+// Routine Description:
+//
+// This function transfer control to unwind. It is used by the MIPS
+// compiler when a goto out of the body or a try statement occurs.
+//
+// Arguments:
+//
+// EstablishFrame (r.3) - Supplies the establisher frame pointer of the
+// target of the unwind.
+//
+// TargetPc (r.4) - Supplies the target instruction address where control
+// is to be transfered to after the unwind operation is complete.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ NESTED_ENTRY (__jump_unwind, STK_MIN_FRAME+8, 0, 0)
+ PROLOGUE_END(__jump_unwind)
+
+ li r.5, 0 // set NULL exception record address
+ li r.6, 0 // set destination return value
+ bl ..RtlUnwind // unwind to specified target
+ .znop ..RtlUnwind
+
+ NESTED_EXIT (__jump_unwind, STK_MIN_FRAME+8, 0, 0)
diff --git a/private/crt32/misc/ppc/longjmp.s b/private/crt32/misc/ppc/longjmp.s
new file mode 100644
index 000000000..d5149f869
--- /dev/null
+++ b/private/crt32/misc/ppc/longjmp.s
@@ -0,0 +1,143 @@
+//++
+//
+// Copyright (c) 1993 IBM Corporation and Microsoft Corporation
+//
+// Module Name:
+//
+// longjmp.s
+//
+// Abstract:
+//
+// This module implements the MIPS specific routine to perform a long
+// jump operation.
+//
+// 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:
+//
+// Rick Simpson 13-Oct-1993
+//
+// based on MIPS version by David N. Cutler (davec) 2-Apr-1993
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+//--
+
+//list(off)
+#include "ksppc.h"
+//list(on)
+ .extern ..RtlUnwind
+
+//++
+//
+// 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 (r.3) - Supplies the address of a jump buffer that contains
+// jump information.
+//
+// ReturnValue (r.4) - Supplies the value that is to be returned to the
+// caller of setjmp().
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY (longjmp)
+
+ cmpwi cr.0, r.4, 0 // check return value for 0
+ lwz r.0, JbType (r.3) // load safe/unsafe switch
+ cmpwi cr.1, r.0, 0 // check for unsafe
+ bne cr.0, Lj10 // branch if not trying to return 0
+ li r.4, 1 // force return value to be non-zero
+Lj10: bne cr.1, ...Lj20 // branch if safe form of setjmp/longjmp
+
+//
+// Provide unsafe handling of longjmp.
+//
+
+ lfd f.14, JbFpr14 (r.3) // reload n-v floating point regs
+ lfd f.15, JbFpr15 (r.3)
+ lfd f.16, JbFpr16 (r.3)
+ lfd f.17, JbFpr17 (r.3)
+ lfd f.18, JbFpr18 (r.3)
+ lfd f.19, JbFpr19 (r.3)
+ lfd f.20, JbFpr20 (r.3)
+ lfd f.21, JbFpr21 (r.3)
+ lfd f.22, JbFpr22 (r.3)
+ lfd f.23, JbFpr23 (r.3)
+ lfd f.24, JbFpr24 (r.3)
+ lfd f.25, JbFpr25 (r.3)
+ lfd f.26, JbFpr26 (r.3)
+ lfd f.27, JbFpr27 (r.3)
+ lfd f.28, JbFpr28 (r.3)
+ lfd f.29, JbFpr29 (r.3)
+ lfd f.30, JbFpr30 (r.3)
+ lfd f.31, JbFpr31 (r.3)
+
+ lwz r.13, JbGpr13 (r.3) // reload n-v general regs
+ lwz r.14, JbGpr14 (r.3)
+ lwz r.15, JbGpr15 (r.3)
+ lwz r.16, JbGpr16 (r.3)
+ lwz r.17, JbGpr17 (r.3)
+ lwz r.18, JbGpr18 (r.3)
+ lwz r.19, JbGpr19 (r.3)
+ lwz r.20, JbGpr20 (r.3)
+ lwz r.21, JbGpr21 (r.3)
+ lwz r.22, JbGpr22 (r.3)
+ lwz r.23, JbGpr23 (r.3)
+ lwz r.24, JbGpr24 (r.3)
+ lwz r.25, JbGpr25 (r.3)
+ lwz r.26, JbGpr26 (r.3)
+ lwz r.27, JbGpr27 (r.3)
+ lwz r.28, JbGpr28 (r.3)
+ lwz r.29, JbGpr29 (r.3)
+ lwz r.30, JbGpr30 (r.3)
+ lwz r.31, JbGpr31 (r.3)
+
+ lwz r.5, JbIar (r.3) // get setjmp return address
+ lwz r.6, JbCr (r.3) // get saved CR
+ mtlr r.5 // return addr -> LR
+ lwz r.1, JbGpr1 (r.3) // restore stack pointer
+ lwz r.2, JbGpr2 (r.3) // restore TOC pointer
+ mtcrf 0xff,r.6 // saved CR -> CR
+ mr r.3, r.4 // return value from longjmp()
+ blr // jump back to setjmp() site
+
+ DUMMY_EXIT (longjmp)
+
+
+//
+// Provide safe handling of longjmp.
+//
+
+ NESTED_ENTRY(.Lj20, STK_MIN_FRAME+8, 0, 0)
+ PROLOGUE_END(.Lj20)
+
+ mr r.6, r.4 // set return value (4th arg)
+ li r.5, 0 // set exception record address (3rd arg)
+ lwz r.4, 4 (r.3) // set target instr address (2nd arg)
+ lwz r.3, 0 (r.3) // set target frame address (1st arg)
+ bl ..RtlUnwind // finish in common code
+ .znop ..RtlUnwind
+
+ NESTED_EXIT(.Lj20, STK_MIN_FRAME+8, 0, 0)
diff --git a/private/crt32/misc/ppc/miscasm.s b/private/crt32/misc/ppc/miscasm.s
new file mode 100644
index 000000000..8fab2f64e
--- /dev/null
+++ b/private/crt32/misc/ppc/miscasm.s
@@ -0,0 +1,273 @@
+//
+// Miscellaneous assembly-language routines and data for
+// PowerPC RTL
+//
+#include "ksppc.h"
+//
+// Copyright 1993 IBM Corporation
+//
+// By Rick Simpson, 17 August 1993
+//
+//-----------------------------------------------------------------------------
+//
+// These routines save and restore only the GPRs and FPRs.
+//
+// Saving and restoring of other non-volatile registers (LR, certain
+// fields of CR) is the responsibility of in-line prologue and epilogue
+// code.
+//
+//-----------------------------------------------------------------------------
+//
+// _savegpr_<n>
+// Inputs:
+// r12 = pointer to END of GPR save area
+// LR = return address to invoking prologue
+// Saves GPR<n> through GPR31 in area preceeding where r12 points
+//
+// _savefpr_<n>
+// Inputs:
+// r1 = pointer to stack frame header
+// LR = return address to invoking prologue
+// Saves FPR<m> through FPR31 in area preceeding stack frame header
+//
+//-----------------------------------------------------------------------------
+//
+// _restgpr_<n>
+// Inputs:
+// r12 = pointer to END of GPR save area
+// LR = return address to invoking prologue
+// Restores GPR<n> through GPR31 from area preceeding where r12 points
+//
+// _restfpr_<m>
+// Inputs:
+// r1 = pointer to stack frame header
+// LR = return address to invoking prologue
+// Restores FPR<m> through FPR31 from area preceeding stack frame header
+//
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+//
+// _savegpr_<n> -- Save GPRs when FPRs are also saved
+//
+// On entry:
+// r12 = address of END of GPR save area
+// LR = return address to prologue
+//
+// Saves GPR<n> through GPR31 in area preceeding where r12 points
+//
+//-----------------------------------------------------------------------------
+
+ FN_TABLE(_savegpr_13,0,1)
+ DUMMY_ENTRY(_savegpr_13)
+ .set _savegpr_13.body,.._savegpr_13-1
+ stw r13, -4*(32-13)(r12)
+ DUMMY_ENTRY(_savegpr_14)
+ stw r14, -4*(32-14)(r12)
+ DUMMY_ENTRY(_savegpr_15)
+ stw r15, -4*(32-15)(r12)
+ DUMMY_ENTRY(_savegpr_16)
+ stw r16, -4*(32-16)(r12)
+ DUMMY_ENTRY(_savegpr_17)
+ stw r17, -4*(32-17)(r12)
+ DUMMY_ENTRY(_savegpr_18)
+ stw r18, -4*(32-18)(r12)
+ DUMMY_ENTRY(_savegpr_19)
+ stw r19, -4*(32-19)(r12)
+ DUMMY_ENTRY(_savegpr_20)
+ stw r20, -4*(32-20)(r12)
+ DUMMY_ENTRY(_savegpr_21)
+ stw r21, -4*(32-21)(r12)
+ DUMMY_ENTRY(_savegpr_22)
+ stw r22, -4*(32-22)(r12)
+ DUMMY_ENTRY(_savegpr_23)
+ stw r23, -4*(32-23)(r12)
+ DUMMY_ENTRY(_savegpr_24)
+ stw r24, -4*(32-24)(r12)
+ DUMMY_ENTRY(_savegpr_25)
+ stw r25, -4*(32-25)(r12)
+ DUMMY_ENTRY(_savegpr_26)
+ stw r26, -4*(32-26)(r12)
+ DUMMY_ENTRY(_savegpr_27)
+ stw r27, -4*(32-27)(r12)
+ DUMMY_ENTRY(_savegpr_28)
+ stw r28, -4*(32-28)(r12)
+ DUMMY_ENTRY(_savegpr_29)
+ stw r29, -4*(32-29)(r12)
+ DUMMY_ENTRY(_savegpr_30)
+ stw r30, -4*(32-30)(r12)
+ DUMMY_ENTRY(_savegpr_31)
+ stw r31, -4*(32-31)(r12)
+ SPECIAL_EXIT(_savegpr_13)
+
+//-----------------------------------------------------------------------------
+//
+// _savefpr_<n> -- Saves FPRs
+//
+// On entry:
+// r1 = pointer to stack frame header
+// LR = return address to prologue
+//
+// Saves FPR<n> through FPR31 in area preceeding stack frame header
+//
+//-----------------------------------------------------------------------------
+
+ FN_TABLE(_savefpr_14,0,1)
+ DUMMY_ENTRY(_savefpr_14)
+ .set _savefpr_14.body,.._savefpr_14-1
+ stfd f14, -8*(32-14)(r1)
+ DUMMY_ENTRY(_savefpr_15)
+ stfd f15, -8*(32-15)(r1)
+ DUMMY_ENTRY(_savefpr_16)
+ stfd f16, -8*(32-16)(r1)
+ DUMMY_ENTRY(_savefpr_17)
+ stfd f17, -8*(32-17)(r1)
+ DUMMY_ENTRY(_savefpr_18)
+ stfd f18, -8*(32-18)(r1)
+ DUMMY_ENTRY(_savefpr_19)
+ stfd f19, -8*(32-19)(r1)
+ DUMMY_ENTRY(_savefpr_20)
+ stfd f20, -8*(32-20)(r1)
+ DUMMY_ENTRY(_savefpr_21)
+ stfd f21, -8*(32-21)(r1)
+ DUMMY_ENTRY(_savefpr_22)
+ stfd f22, -8*(32-22)(r1)
+ DUMMY_ENTRY(_savefpr_23)
+ stfd f23, -8*(32-23)(r1)
+ DUMMY_ENTRY(_savefpr_24)
+ stfd f24, -8*(32-24)(r1)
+ DUMMY_ENTRY(_savefpr_25)
+ stfd f25, -8*(32-25)(r1)
+ DUMMY_ENTRY(_savefpr_26)
+ stfd f26, -8*(32-26)(r1)
+ DUMMY_ENTRY(_savefpr_27)
+ stfd f27, -8*(32-27)(r1)
+ DUMMY_ENTRY(_savefpr_28)
+ stfd f28, -8*(32-28)(r1)
+ DUMMY_ENTRY(_savefpr_29)
+ stfd f29, -8*(32-29)(r1)
+ DUMMY_ENTRY(_savefpr_30)
+ stfd f30, -8*(32-30)(r1)
+ DUMMY_ENTRY(_savefpr_31)
+ stfd f31, -8*(32-31)(r1)
+ SPECIAL_EXIT(_savefpr_14)
+
+//-----------------------------------------------------------------------------
+//
+// _restgpr_<n> -- Restore GPRs when FPRs are also restored
+//
+// On entry:
+// r12 = address of END of GPR save area
+// LR = return address
+//
+// Restores GPR<n> through GPR31 from area preceeding where r12 points
+//
+//-----------------------------------------------------------------------------
+
+ FN_TABLE(_restgpr_13,0,2)
+ DUMMY_ENTRY(_restgpr_13)
+ .set _restgpr_13.body,.._restgpr_13-2
+ lwz r13, -4*(32-13)(r12)
+ DUMMY_ENTRY(_restgpr_14)
+ lwz r14, -4*(32-14)(r12)
+ DUMMY_ENTRY(_restgpr_15)
+ lwz r15, -4*(32-15)(r12)
+ DUMMY_ENTRY(_restgpr_16)
+ lwz r16, -4*(32-16)(r12)
+ DUMMY_ENTRY(_restgpr_17)
+ lwz r17, -4*(32-17)(r12)
+ DUMMY_ENTRY(_restgpr_18)
+ lwz r18, -4*(32-18)(r12)
+ DUMMY_ENTRY(_restgpr_19)
+ lwz r19, -4*(32-19)(r12)
+ DUMMY_ENTRY(_restgpr_20)
+ lwz r20, -4*(32-20)(r12)
+ DUMMY_ENTRY(_restgpr_21)
+ lwz r21, -4*(32-21)(r12)
+ DUMMY_ENTRY(_restgpr_22)
+ lwz r22, -4*(32-22)(r12)
+ DUMMY_ENTRY(_restgpr_23)
+ lwz r23, -4*(32-23)(r12)
+ DUMMY_ENTRY(_restgpr_24)
+ lwz r24, -4*(32-24)(r12)
+ DUMMY_ENTRY(_restgpr_25)
+ lwz r25, -4*(32-25)(r12)
+ DUMMY_ENTRY(_restgpr_26)
+ lwz r26, -4*(32-26)(r12)
+ DUMMY_ENTRY(_restgpr_27)
+ lwz r27, -4*(32-27)(r12)
+ DUMMY_ENTRY(_restgpr_28)
+ lwz r28, -4*(32-28)(r12)
+ DUMMY_ENTRY(_restgpr_29)
+ lwz r29, -4*(32-29)(r12)
+ DUMMY_ENTRY(_restgpr_30)
+ lwz r30, -4*(32-30)(r12)
+ DUMMY_ENTRY(_restgpr_31)
+ lwz r31, -4*(32-31)(r12)
+ SPECIAL_EXIT(_restgpr_13)
+
+//-----------------------------------------------------------------------------
+//
+// _restfpr_<n> -- Restores FPRs
+//
+// On entry:
+// r1 = pointer to stack frame header
+// LR = return address
+//
+// Restores FPR<n> through FPR31 from area preceeding stack frame header
+//
+//-----------------------------------------------------------------------------
+
+ FN_TABLE(_restfpr_14,0,2)
+ DUMMY_ENTRY(_restfpr_14)
+ .set _restfpr_14.body,.._restfpr_14-2
+ lfd f14, -8*(32-14)(r1)
+ DUMMY_ENTRY(_restfpr_15)
+ lfd f15, -8*(32-15)(r1)
+ DUMMY_ENTRY(_restfpr_16)
+ lfd f16, -8*(32-16)(r1)
+ DUMMY_ENTRY(_restfpr_17)
+ lfd f17, -8*(32-17)(r1)
+ DUMMY_ENTRY(_restfpr_18)
+ lfd f18, -8*(32-18)(r1)
+ DUMMY_ENTRY(_restfpr_19)
+ lfd f19, -8*(32-19)(r1)
+ DUMMY_ENTRY(_restfpr_20)
+ lfd f20, -8*(32-20)(r1)
+ DUMMY_ENTRY(_restfpr_21)
+ lfd f21, -8*(32-21)(r1)
+ DUMMY_ENTRY(_restfpr_22)
+ lfd f22, -8*(32-22)(r1)
+ DUMMY_ENTRY(_restfpr_23)
+ lfd f23, -8*(32-23)(r1)
+ DUMMY_ENTRY(_restfpr_24)
+ lfd f24, -8*(32-24)(r1)
+ DUMMY_ENTRY(_restfpr_25)
+ lfd f25, -8*(32-25)(r1)
+ DUMMY_ENTRY(_restfpr_26)
+ lfd f26, -8*(32-26)(r1)
+ DUMMY_ENTRY(_restfpr_27)
+ lfd f27, -8*(32-27)(r1)
+ DUMMY_ENTRY(_restfpr_28)
+ lfd f28, -8*(32-28)(r1)
+ DUMMY_ENTRY(_restfpr_29)
+ lfd f29, -8*(32-29)(r1)
+ DUMMY_ENTRY(_restfpr_30)
+ lfd f30, -8*(32-30)(r1)
+ DUMMY_ENTRY(_restfpr_31)
+ lfd f31, -8*(32-31)(r1)
+ SPECIAL_EXIT(_restfpr_14)
+
+//
+// This is a copy of the function table entries for the millicode. It's
+// used with the PPCKD_SYMBOL_SEARCH mechanism in vunwind.c to allow
+// for older versions of miscasm.obj.
+//
+
+ .reldata
+ .globl _millicode_table
+_millicode_table:
+ .long .._savegpr_13, _savegpr_13.end, 0, 1, .._savegpr_13
+ .long .._savefpr_14, _savefpr_14.end, 0, 1, .._savefpr_14
+ .long .._restgpr_13, _restgpr_13.end, 0, 2, .._restgpr_13
+ .long .._restfpr_14, _restfpr_14.end, 0, 2, .._restfpr_14
diff --git a/private/crt32/misc/ppc/setjmp.s b/private/crt32/misc/ppc/setjmp.s
new file mode 100644
index 000000000..65b58adf5
--- /dev/null
+++ b/private/crt32/misc/ppc/setjmp.s
@@ -0,0 +1,138 @@
+//++
+//
+// Copyright (c) 1993 IBM Corporation and Microsoft Corporation
+//
+// Module Name:
+//
+// setjmp.s
+//
+// Abstract:
+//
+// This module implements the MIPS specific routine to perform a setjmp.
+//
+// N.B. This module conditionally provides UNSAFE handling of setjmp and
+// which is NOT integrated with structured exception handling. The
+// determination is made based on whether an uninitialized variable
+// has been set to a nonzero value.
+//
+// Author:
+//
+// Rick Simpson 13-Oct-1993
+//
+// based on MIPS version by David N. Cutler (davec) 7-Apr-1993
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+//--
+
+//list(off)
+#include "ksppc.h"
+//list(on)
+
+//
+// Define variable that will cause setjmp/longjmp to be safe or unsafe with
+// respect to structured exception handling.
+//
+
+ .globl _setjmpexused
+ .comm _setjmpexused , 4
+
+//++
+//
+// int
+// setjmp (
+// IN jmp_buf JumpBuffer
+// )
+//
+// Routine Description:
+//
+// This function saved the current nonvolatile register state in the
+// specified jump buffer and returns a function vlaue of zero.
+//
+// Arguments:
+//
+// JumpBuffer (r.3) - Supplies the address of a jump buffer to store the
+// jump information.
+//
+// Return Value:
+//
+// A value of zero is returned.
+//
+//--
+
+ LEAF_ENTRY (setjmp)
+
+//
+// If _setjmpexused is non-NULL, it contains the entry point address
+// of the safe version of setjmp, ..setjmpex. We branch thru the CTR
+// using this variable rather than branching directly to the entry point
+// to avoid assembling a hard reference to ..setjmpex into this code.
+// CTR is used to avoid killing caller's LR.
+//
+
+ lwz r.4, [toc] _setjmpexused (r.toc) // get address of switch variable
+ lwz r.0, 0 (r.4) // get value of switch variable
+ cmpwi r.0, 0 // see if switch is NULL
+ mtctr r.0 // if switch is non-NULL,
+ bnectr // branch to safe setjmp() routine
+
+//
+// Provide unsafe handling of setjmp.
+//
+
+ mflr r.0 // fetch incoming LR
+ mfcr r.4 // fetch incoming CR
+
+ stfd f.14, JbFpr14 (r.3) // save n-v floating point regs
+ stfd f.15, JbFpr15 (r.3)
+ stfd f.16, JbFpr16 (r.3)
+ stfd f.17, JbFpr17 (r.3)
+ stfd f.18, JbFpr18 (r.3)
+ stfd f.19, JbFpr19 (r.3)
+ stfd f.20, JbFpr20 (r.3)
+ stfd f.21, JbFpr21 (r.3)
+ stfd f.22, JbFpr22 (r.3)
+ stfd f.23, JbFpr23 (r.3)
+ stfd f.24, JbFpr24 (r.3)
+ stfd f.25, JbFpr25 (r.3)
+ stfd f.26, JbFpr26 (r.3)
+ stfd f.27, JbFpr27 (r.3)
+ stfd f.28, JbFpr28 (r.3)
+ stfd f.29, JbFpr29 (r.3)
+ stfd f.30, JbFpr30 (r.3)
+ stfd f.31, JbFpr31 (r.3)
+
+ stw r.13, JbGpr13 (r.3) // save n-v general regs
+ stw r.14, JbGpr14 (r.3)
+ stw r.15, JbGpr15 (r.3)
+ stw r.16, JbGpr16 (r.3)
+ stw r.17, JbGpr17 (r.3)
+ stw r.18, JbGpr18 (r.3)
+ stw r.19, JbGpr19 (r.3)
+ stw r.20, JbGpr20 (r.3)
+ stw r.21, JbGpr21 (r.3)
+ stw r.22, JbGpr22 (r.3)
+ stw r.23, JbGpr23 (r.3)
+ stw r.24, JbGpr24 (r.3)
+ stw r.25, JbGpr25 (r.3)
+ stw r.26, JbGpr26 (r.3)
+ stw r.27, JbGpr27 (r.3)
+ stw r.28, JbGpr28 (r.3)
+ stw r.29, JbGpr29 (r.3)
+ stw r.30, JbGpr30 (r.3)
+ stw r.31, JbGpr31 (r.3)
+
+ stw r.0, JbIar (r.3) // setjmp return address
+ stw r.4, JbCr (r.3) // save CR (n-v part)
+ stw r.sp, JbGpr1 (r.3) // save stack pointer
+ stw r.toc, JbGpr2 (r.3) // save TOC pointer
+ li r.0, 0
+ stw r.0, JbType (r.3) // clean safe setjmp flag
+
+ li r.3, 0 // set return value
+ LEAF_EXIT (setjmp) // return
+
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)
diff --git a/private/crt32/misc/ppc/sources b/private/crt32/misc/ppc/sources
new file mode 100644
index 000000000..520ce611c
--- /dev/null
+++ b/private/crt32/misc/ppc/sources
@@ -0,0 +1,6 @@
+PPC_SOURCES=ppc\chandler.c \
+ ppc\setjmp.s \
+ ppc\setjmpex.s \
+ ppc\longjmp.s \
+ ppc\jmpuwind.s \
+ ppc\miscasm.s