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
 

Reply via email to