154389Storek/* 2*61172Sbostic * Copyright (c) 1992, 1993 3*61172Sbostic * The Regents of the University of California. All rights reserved. 454389Storek * 554389Storek * This software was developed by the Computer Systems Engineering group 654389Storek * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 754389Storek * contributed to Berkeley. 854389Storek * 954389Storek * %sccs.include.redist.c% 1054389Storek * 1154389Storek * from: $Header: setjmp.s,v 1.2 92/06/25 03:18:43 torek Exp $ 1254389Storek */ 1354389Storek 1454389Storek#if defined(LIBC_SCCS) && !defined(lint) 15*61172Sbostic .asciz "@(#)setjmp.s 8.1 (Berkeley) 06/04/93" 1654389Storek#endif /* LIBC_SCCS and not lint */ 1754389Storek 1854389Storek/* 1954389Storek * C library -- setjmp, longjmp 2054389Storek * 2154389Storek * longjmp(a,v) 2254389Storek * will generate a "return(v)" from 2354389Storek * the last call to 2454389Storek * setjmp(a) 2554389Storek * by restoring registers from the stack, 2654389Storek * and a struct sigcontext, see <signal.h> 2754389Storek */ 2854389Storek 2954389Storek#include "SYS.h" 3054389Storek 3154389StorekENTRY(setjmp) 3254389Storek /* 3354389Storek * We use the caller's `arg dump' area (%sp+0x44; there are 6 ints 3454389Storek * reserved there for us) to avoid having to allocate stack space 3554389Storek * here. 3654389Storek */ 3754389Storek mov %o0, %o2 /* build sigcontext in [%o2] */ 3854389Storek mov 1, %o0 /* SIG_BLOCK */ 3954389Storek mov SYS_sigprocmask, %g1 4054389Storek clr %o1 /* sigprocmask(SIG_BLOCK, (sigset_t *)NULL) */ 4154389Storek t ST_SYSCALL 4254389Storek st %o0, [%o2 + 4] /* sc.sc_mask = current mask; */ 4354389Storek mov SYS_sigaltstack, %g1 4454389Storek clr %o0 /* sigstack(NULL, &foo) */ 4554389Storek add %sp, 0x48, %o1 /* (foo being in arg dump area) */ 4654389Storek t ST_SYSCALL 4754389Storek ld [%sp + 0x50], %o0 /* foo.ss_flags */ 4854389Storek and %o0, 1, %o1 /* onstack = foo.ss_flags & 1; */ 4954389Storek st %o0, [%o2 + 0] /* sc.sc_onstack = current onstack; */ 5054389Storek st %sp, [%o2 + 8] /* sc.sc_sp = sp (both ours and caller's) */ 5154389Storek add %o7, 8, %o0 5254389Storek st %o0, [%o2 + 12] /* sc.sc_pc = return_pc */ 5354389Storek add %o7, 12, %o0 5454389Storek st %o0, [%o2 + 16] /* sc.sc_npc = return_pc + 4 */ 5554389Storek st %g0, [%o2 + 20] /* sc.sc_psr = (clean psr) */ 5654389Storek st %fp, [%o2 + 24] /* sc.sc_g1 = %fp (misuse, but what the heck) */ 5754389Storek /* sc.sc_o0 = random(), set in longjmp */ 5854389Storek retl /* return 0 */ 5954389Storek clr %o0 6054389Storek 6154389Storek/* 6254389Storek * All we need to do here is force sigreturn to load a new stack pointer, 6354389Storek * new <pc,npc>, and appropriate %o0 return value from the sigcontext built 6454389Storek * in setjmp. The %i and %l registers will be reloaded from the place to 6554389Storek * which %sp points, due to sigreturn() semantics (sigreturn does not modify 6654389Storek * the window pointer in the psr, hence it must force all windows to reload). 6754389Storek */ 6854389StorekENTRY(longjmp) 6954389Storek save %sp, -96, %sp 7054389Storek ld [%i0 + 8], %o2 /* make sure sc->sc_sp, sc->sc_fp nonzero */ 7154389Storek ld [%i0 + 24], %o3 7254389Storek orcc %o2, %o3, %g0 7354389Storek bz Lbotch 7454389Storek tst %i1 /* if (v == 0) v = 1; */ 7554389Storek bz,a 1f 7654389Storek mov 1, %i1 7754389Storek1: 7854389Storek st %i1, [%i0 + 28] /* sc.sc_o0 = v; */ 7954389Storek mov SYS_sigreturn, %g1 8054389Storek mov %i0, %o0 8154389Storek t ST_SYSCALL /* sigreturn(scp); */ 8254389Storek 8354389StorekLbotch: 8454389Storek /* oops, caller botched it */ 8554389Storek call _longjmperror 8654389Storek nop 8754389Storek unimp 0 88