Save a few global registers during set/longjmp - at least the application

registers and the only currently used system register (%g7).
Sparc now passes the setjmp tests (and should be able to build perl again).
This commit is contained in:
martin 2011-04-30 23:41:12 +00:00
parent 9881f8de04
commit 251de2dee0
3 changed files with 45 additions and 10 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: _setjmp.S,v 1.8 2008/04/28 20:22:57 martin Exp $ */
/* $NetBSD: _setjmp.S,v 1.9 2011/04/30 23:41:12 martin Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -33,7 +33,7 @@
#include <machine/trap.h>
#if defined(LIBC_SCCS) && !defined(lint)
RCSID("$NetBSD: _setjmp.S,v 1.8 2008/04/28 20:22:57 martin Exp $")
RCSID("$NetBSD: _setjmp.S,v 1.9 2011/04/30 23:41:12 martin Exp $")
#endif /* LIBC_SCCS and not lint */
/*
@ -47,6 +47,12 @@ RCSID("$NetBSD: _setjmp.S,v 1.8 2008/04/28 20:22:57 martin Exp $")
*/
ENTRY(_setjmp)
/* store important globals, sigsetjmp compatible */
st %g3, [%o0 + 16]
st %g2, [%o0 + 24]
st %g4, [%o0 + 48]
st %g7, [%o0 + 52]
st %sp, [%o0+0] /* store caller's stack pointer */
st %o7, [%o0+4] /* and the return pc */
retl
@ -60,6 +66,12 @@ ENTRY(_longjmp)
0:
t ST_FLUSHWIN ! flush register windows out to the stack
/* restore globals */
ld [%o0 + 16], %g3
ld [%o0 + 24], %g2
ld [%o0 + 48], %g4
ld [%o0 + 52], %g7
/*
* We restore the saved stack pointer to %fp, then issue
* a `restore' instruction which will reload the register

View File

@ -1,4 +1,4 @@
/* $NetBSD: longjmp.c,v 1.2 2008/04/28 20:22:57 martin Exp $ */
/* $NetBSD: longjmp.c,v 1.3 2011/04/30 23:41:12 martin Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@ -35,11 +35,27 @@
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#define __LIBC12_SOURCE__
#include <setjmp.h>
#include <compat/include/setjmp.h>
struct __jmp_buf_regs_t {
__greg_t g4;
__greg_t g7;
__greg_t save_mask;
};
/*
* setjmp.S uses hard coded offsets into the jump_buf,
* make sure any changes cause a compile failure here
*/
__CTASSERT(56 == offsetof(struct __jmp_buf_regs_t,save_mask) +
sizeof(struct sigcontext));
__CTASSERT(sizeof(sigjmp_buf) >= sizeof(struct __jmp_buf_regs_t) +
sizeof(struct sigcontext));
/*
* Use setcontext to reload the stack pointer, program counter <pc,npc>, and
* set the return value in %o0. The %i and %l registers will be reloaded
@ -49,14 +65,15 @@ void
__longjmp14(jmp_buf env, int val)
{
struct sigcontext *sc = (void *)env;
struct __jmp_buf_regs_t *r = (void*)&sc[1];
ucontext_t uc;
/* Ensure non-zero SP */
if (sc->sc_sp == 0)
goto err;
/* Initialise the fields we're going to use */
uc.uc_link = 0;
/* Initialise the context */
memset(&uc, 0, sizeof(uc));
/*
* Set _UC_{SET,CLR}STACK according to SS_ONSTACK.
@ -71,8 +88,12 @@ __longjmp14(jmp_buf env, int val)
/* Extract PSR, PC, NPC and SP from jmp_buf */
uc.uc_mcontext.__gregs[_REG_PSR] = sc->sc_psr;
uc.uc_mcontext.__gregs[_REG_PC] = sc->sc_pc;
uc.uc_mcontext.__gregs[_REG_nPC] = sc->sc_npc;
uc.uc_mcontext.__gregs[_REG_nPC] = sc->sc_pc+4;
uc.uc_mcontext.__gregs[_REG_O6] = sc->sc_sp;
uc.uc_mcontext.__gregs[_REG_G2] = sc->sc_g1;
uc.uc_mcontext.__gregs[_REG_G3] = sc->sc_npc;
uc.uc_mcontext.__gregs[_REG_G4] = r->g4;
uc.uc_mcontext.__gregs[_REG_G7] = r->g7;
/* Set the return value; make sure it's non-zero */
uc.uc_mcontext.__gregs[_REG_O0] = (val != 0 ? val : 1);

View File

@ -1,4 +1,4 @@
/* $NetBSD: setjmp.S,v 1.11 2007/10/08 13:06:00 uwe Exp $ */
/* $NetBSD: setjmp.S,v 1.12 2011/04/30 23:41:13 martin Exp $ */
/*
* Copyright (c) 1992, 1993
@ -40,7 +40,7 @@
#if 0
.asciz "@(#)setjmp.s 8.1 (Berkeley) 6/4/93"
#else
RCSID("$NetBSD: setjmp.S,v 1.11 2007/10/08 13:06:00 uwe Exp $")
RCSID("$NetBSD: setjmp.S,v 1.12 2011/04/30 23:41:13 martin Exp $")
#endif
#endif /* LIBC_SCCS and not lint */
@ -78,9 +78,11 @@ ENTRY(__setjmp14)
st %fp, [%i0 + 8] /* sc.sc_sp = (caller's) sp */
add %i7, 8, %o0
st %o0, [%i0 + 12] /* sc.sc_pc = return_pc */
add %i7, 12, %o0
st %o0, [%i0 + 16] /* sc.sc_npc = return_pc + 4 */
st %g3, [%i0 + 16] /* sc.sc_npc */
st %g0, [%i0 + 20] /* sc.sc_psr = (clean psr) */
st %g2, [%i0 + 24]
st %g4, [%i0 + 48]
st %g7, [%i0 + 52]
ret /* return 0 */
restore %g0, %g0, %o0