Module Name: src Committed By: martin Date: Sat Apr 30 23:41:13 UTC 2011
Modified Files: src/lib/libc/arch/sparc/gen: _setjmp.S longjmp.c setjmp.S Log Message: 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). To generate a diff of this commit: cvs rdiff -u -r1.8 -r1.9 src/lib/libc/arch/sparc/gen/_setjmp.S cvs rdiff -u -r1.2 -r1.3 src/lib/libc/arch/sparc/gen/longjmp.c cvs rdiff -u -r1.11 -r1.12 src/lib/libc/arch/sparc/gen/setjmp.S Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/arch/sparc/gen/_setjmp.S diff -u src/lib/libc/arch/sparc/gen/_setjmp.S:1.8 src/lib/libc/arch/sparc/gen/_setjmp.S:1.9 --- src/lib/libc/arch/sparc/gen/_setjmp.S:1.8 Mon Apr 28 20:22:57 2008 +++ src/lib/libc/arch/sparc/gen/_setjmp.S Sat Apr 30 23:41:12 2011 @@ -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 @@ */ 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 @@ 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 Index: src/lib/libc/arch/sparc/gen/longjmp.c diff -u src/lib/libc/arch/sparc/gen/longjmp.c:1.2 src/lib/libc/arch/sparc/gen/longjmp.c:1.3 --- src/lib/libc/arch/sparc/gen/longjmp.c:1.2 Mon Apr 28 20:22:57 2008 +++ src/lib/libc/arch/sparc/gen/longjmp.c Sat Apr 30 23:41:12 2011 @@ -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 @@ __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 @@ /* 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); Index: src/lib/libc/arch/sparc/gen/setjmp.S diff -u src/lib/libc/arch/sparc/gen/setjmp.S:1.11 src/lib/libc/arch/sparc/gen/setjmp.S:1.12 --- src/lib/libc/arch/sparc/gen/setjmp.S:1.11 Mon Oct 8 13:06:00 2007 +++ src/lib/libc/arch/sparc/gen/setjmp.S Sat Apr 30 23:41:13 2011 @@ -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 @@ 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