summaryrefslogtreecommitdiff
path: root/lib/libc/arch/sparc
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2004-05-04 15:57:07 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2004-05-04 15:57:07 +0000
commit6ad82160203c4fca197d07d09d81c1e625169875 (patch)
tree7984d0cb851ffd4d739922c29b323a412d6cc795 /lib/libc/arch/sparc
parentb9eb02a88d66a896d3db2744fcf33d9409b6762e (diff)
In _longjmp(), flush windows rather than attempting to backtrack manually,
since the latter is not reliable in all cases. This allows ruby to work on sparc64. Problem spotted by claudio@; fix adapted from NetBSD for sparc, FreeBSD for sparc64; ok deraadt@
Diffstat (limited to 'lib/libc/arch/sparc')
-rw-r--r--lib/libc/arch/sparc/gen/_setjmp.S47
1 files changed, 19 insertions, 28 deletions
diff --git a/lib/libc/arch/sparc/gen/_setjmp.S b/lib/libc/arch/sparc/gen/_setjmp.S
index 487970b0c4d..3c6f3d05883 100644
--- a/lib/libc/arch/sparc/gen/_setjmp.S
+++ b/lib/libc/arch/sparc/gen/_setjmp.S
@@ -34,7 +34,7 @@
#if defined(LIBC_SCCS)
.text
- .asciz "$OpenBSD: _setjmp.S,v 1.5 2003/06/02 20:18:32 millert Exp $"
+ .asciz "$OpenBSD: _setjmp.S,v 1.6 2004/05/04 15:57:04 miod Exp $"
#endif /* LIBC_SCCS */
/*
@@ -44,44 +44,35 @@
* will generate a "return(v?v:1)" from
* the last call to
* _setjmp(a)
- * by unwinding the call stack.
+ * by restoring the previous context.
* The previous signal state is NOT restored.
*/
#include "DEFS.h"
+#include <machine/trap.h> /* T_FLUSHWIN */
+#define CCFSZ 96 /* from locore.S */
ENTRY(_setjmp)
- st %sp, [%o0+0] /* store caller's stack pointer */
- st %o7, [%o0+4] /* ... return pc */
- st %fp, [%o0+8] /* ... and frame pointer */
+ st %sp, [%o0 + 0] /* store caller's stack pointer */
+ st %o7, [%o0 + 4] /* ... and return pc */
retl
clr %o0 ! return 0
ENTRY(_longjmp)
- addcc %o1, %g0, %g6 ! compute v ? v : 1 in a global register
+ sub %sp, CCFSZ, %sp ! set up a local stack frame
+ tst %o1 ! compute v ? v : 1
be,a 0f
- mov 1, %g6
+ mov 1, %o1
0:
- mov %o0, %g1 ! save a in another global register
- ld [%g1+8], %g7 /* get caller's frame */
-1:
- cmp %fp, %g7 ! compare against desired frame
- bl,a 1b ! if below,
- restore ! pop frame and loop
- be,a 2f ! if there,
- ld [%g1+0], %o2 ! fetch return %sp
+ t ST_FLUSHWIN ! flush register windows out to the stack
-Lbotch:
- call _C_LABEL(longjmperror) ! otherwise, went too far; bomb out
- nop
- unimp 0
+ /*
+ * We restore the saved stack pointer to %fp, then issue
+ * a `restore' instruction which will reload the register
+ * window from the stack.
+ */
+ ld [%o0 + 4], %o7 /* restore return pc */
+ ld [%o0 + 0], %fp /* and stack pointer */
-2:
- cmp %o2, %sp ! %sp must not decrease
- bge,a 3f
- mov %o2, %sp ! it is OK, put it in place
- b,a Lbotch
-3:
- ld [%g1+4], %o3 ! fetch pc
- jmp %o3 + 8 ! success, return %g6
- mov %g6, %o0
+ retl ! success, return %g6
+ restore %o1, 0, %o0