summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/sh/setjmp.S
diff options
context:
space:
mode:
Diffstat (limited to 'libc/sysdeps/linux/sh/setjmp.S')
-rw-r--r--libc/sysdeps/linux/sh/setjmp.S71
1 files changed, 61 insertions, 10 deletions
diff --git a/libc/sysdeps/linux/sh/setjmp.S b/libc/sysdeps/linux/sh/setjmp.S
index 3d41876d3..c9fa3b1fb 100644
--- a/libc/sysdeps/linux/sh/setjmp.S
+++ b/libc/sysdeps/linux/sh/setjmp.S
@@ -17,17 +17,54 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#include <features.h>
#define _SETJMP_H
#define _ASM
#include <bits/setjmp.h>
-.text
-.align 4
-.type __sigsetjmp,@function
-.globl __sigsetjmp;
+ .text
+
+/* This just does a tail-call to `__sigsetjmp (ARG, 0)'.
+ We cannot do it in C because it must be a tail-call, so frame-unwinding
+ in setjmp doesn't clobber the state restored by longjmp. */
+
+ .align 4
+ .type _setjmp,@function
+ .globl _setjmp;
+_setjmp:
+ bra __sigsetjmp_intern
+ mov #0, r1
+ .size _setjmp,.-_setjmp;
+
+/* This just does a tail-call to `__sigsetjmp (ARG, 1)'.
+ We cannot do it in C because it must be a tail-call, so frame-unwinding
+ in setjmp doesn't clobber the state restored by longjmp. */
+
+ .align 4
+ .type setjmp,@function
+ .globl setjmp;
+setjmp:
+ bra __sigsetjmp_intern
+ mov #1, r1
+ .size setjmp,.-setjmp;
+
+ .align 4
+ .type __sigsetjmp,@function
+ .globl __sigsetjmp;
__sigsetjmp:
+ mov r0, r1
+__sigsetjmp_intern:
/* Save registers */
+#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__
+ add #(JB_SIZE*4), r4
+ fmov.s fr15, @-r4
+ fmov.s fr14, @-r4
+ fmov.s fr13, @-r4
+ fmov.s fr12, @-r4
+ sts.l fpscr, @-r4
+#else
add #(JB_SIZE-5*4), r4 /* this code doesn't do FP yet */
+#endif
stc.l gbr, @-r4
sts.l pr, @-r4
mov.l r15, @-r4
@@ -39,12 +76,26 @@ __sigsetjmp:
mov.l r9, @-r4
mov.l r8, @-r4
+#if defined __HAVE_ELF__ && defined __HAVE_SHARED__
+ mov.l .LG, r12
+ mova .LG, r0
+ add r0, r12
+ /* Make a tail call to __sigjmp_save; it takes the same args. */
+ mov.l .L1, r0
+ mov.l @(r0,r12),r0
+ jmp @r0
+ mov r1, r0
+ .align 2
+.LG: .long _GLOBAL_OFFSET_TABLE_
+.L1: .long __sigjmp_save@GOT
+#else
/* Make a tail call to __sigjmp_save; it takes the same args. */
- mov.l .L1, r1
- jmp @r1
- nop
+ mov.l .L1, r0
+ braf r0
+ mov r1, r0
+.jmp_loc:
.align 2
-.L1:
- .long __sigjmp_save
-.size __sigsetjmp,.-__sigsetjmp;
+.L1: .long __sigjmp_save - .jmp_loc
+#endif
+ .size __sigsetjmp,.-__sigsetjmp;