Home | History | Annotate | Download | only in gen
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*	Copyright (c) 1988 AT&T	*/
     28 /*	  All Rights Reserved	*/
     29 
     30 	.file	"setjmp.s"
     31 
     32 #include <sys/asm_linkage.h>
     33 
     34 	ANSI_PRAGMA_WEAK(setjmp,function)
     35 	ANSI_PRAGMA_WEAK(longjmp,function)
     36 
     37 #include <sys/trap.h>
     38 
     39 JB_FLAGS	= (0*8)	! offsets in jmpbuf (see siglongjmp.c)
     40 JB_SP		= (1*8)	! words 5 through 11 are unused!
     41 JB_PC		= (2*8)
     42 JB_FP		= (3*8)
     43 JB_I7		= (4*8)
     44 
     45 /*
     46  * setjmp(buf_ptr)
     47  * buf_ptr points to a twelve word array (jmp_buf)
     48  */
     49 	ENTRY(setjmp)
     50 	clr	[%o0 + JB_FLAGS]	! clear flags (used by sigsetjmp)
     51 	stx	%sp, [%o0 + JB_SP]	! save caller's sp
     52 	add	%o7, 8, %o1		! compute return pc
     53 	stx	%o1, [%o0 + JB_PC]	! save pc
     54 	stx	%fp, [%o0 + JB_FP]	! save fp
     55 	stx	%i7, [%o0 + JB_I7]	! save %i7
     56 	retl
     57 	clr	%o0			! return (0)
     58 
     59 	SET_SIZE(setjmp)
     60 
     61 /*
     62  * longjmp(buf_ptr, val)
     63  * buf_ptr points to a jmpbuf which has been initialized by setjmp.
     64  * val is the value we wish to return to setjmp's caller
     65  *
     66  * We flush the register file to the stack by doing a kernel call.
     67  * This is necessary to ensure that the registers we want to
     68  * pick up are stored on the stack, and that subsequent restores
     69  * will function correctly.
     70  *
     71  * sp, fp, and %i7, the caller's return address, are all restored
     72  * to the values they had at the time of the call to setjmp().  All
     73  * other locals, ins and outs are set to potentially random values
     74  * (as per the man page).  This is sufficient to permit the correct
     75  * operation of normal code.
     76  *
     77  * Actually, the above description is not quite correct.  If the routine
     78  * that called setjmp() has not altered the sp value of their frame we
     79  * will restore the remaining locals and ins to the values these
     80  * registers had in the this frame at the time of the call to longjmp()
     81  * (not setjmp()!).  This is intended to help compilers, typically not
     82  * C compilers, that have some registers assigned to fixed purposes,
     83  * and that only alter the values of these registers on function entry
     84  * and exit.
     85  *
     86  * Since a C routine could call setjmp() followed by alloca() and thus
     87  * alter the sp this feature will typically not be helpful for a C
     88  * compiler.
     89  *
     90  * Note also that because the caller of a routine compiled "flat" (without
     91  * register windows) assumes that their ins and locals are preserved,
     92  * routines that call setjmp() must not be flat.
     93  */
     94 	ENTRY(longjmp)
     95 	ta	ST_FLUSH_WINDOWS	! flush all reg windows to the stack.
     96 	ldx	[%o0 + JB_SP], %o2	! sp in %o2 until safe to puke there
     97 	ldx	[%o2 + STACK_BIAS], %l0	! restore locals and ins if we can
     98 	ldx	[%o2 + (1*8) + STACK_BIAS], %l1
     99 	ldx	[%o2 + (2*8) + STACK_BIAS], %l2
    100 	ldx	[%o2 + (3*8) + STACK_BIAS], %l3
    101 	ldx	[%o2 + (4*8) + STACK_BIAS], %l4
    102 	ldx	[%o2 + (5*8) + STACK_BIAS], %l5
    103 	ldx	[%o2 + (6*8) + STACK_BIAS], %l6
    104 	ldx	[%o2 + (7*8) + STACK_BIAS], %l7
    105 	ldx	[%o2 + (8*8) + STACK_BIAS], %i0
    106 	ldx	[%o2 + (9*8) + STACK_BIAS], %i1
    107 	ldx	[%o2 + (10*8) + STACK_BIAS], %i2
    108 	ldx	[%o2 + (11*8) + STACK_BIAS], %i3
    109 	ldx	[%o2 + (12*8) + STACK_BIAS], %i4
    110 	ldx	[%o2 + (13*8) + STACK_BIAS], %i5
    111 	ldx	[%o0 + JB_FP], %fp	! restore fp
    112 	mov	%o2, %sp		! restore sp
    113 	ldx	[%o0 + JB_I7], %i7	! restore %i7
    114 	ldx	[%o0 + JB_PC], %o3	! get new return pc
    115 	tst	%o1			! is return value 0?
    116 	bnz	1f			! no - leave it alone
    117 	sub	%o3, 8, %o7		! normalize return (for adb) (dly slot)
    118 	mov	1, %o1			! yes - set it to one
    119 1:
    120 	retl
    121 	mov	%o1, %o0		! return (val)
    122 
    123 	SET_SIZE(longjmp)
    124