diff options
Diffstat (limited to 'private/crt32/misc/ppc')
-rw-r--r-- | private/crt32/misc/ppc/chandler.c | 222 | ||||
-rw-r--r-- | private/crt32/misc/ppc/cinitone.s | 41 | ||||
-rw-r--r-- | private/crt32/misc/ppc/jmpuwind.s | 162 | ||||
-rw-r--r-- | private/crt32/misc/ppc/longjmp.s | 143 | ||||
-rw-r--r-- | private/crt32/misc/ppc/miscasm.s | 273 | ||||
-rw-r--r-- | private/crt32/misc/ppc/setjmp.s | 138 | ||||
-rw-r--r-- | private/crt32/misc/ppc/setjmpex.s | 194 | ||||
-rw-r--r-- | private/crt32/misc/ppc/sources | 6 |
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 |