summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libc/sysdeps/linux/sh/Makefile2
-rw-r--r--libc/sysdeps/linux/sh/__longjmp.S16
-rw-r--r--libc/sysdeps/linux/sh/setjmp.S71
3 files changed, 78 insertions, 11 deletions
diff --git a/libc/sysdeps/linux/sh/Makefile b/libc/sysdeps/linux/sh/Makefile
index c9cec02c1..e17838db9 100644
--- a/libc/sysdeps/linux/sh/Makefile
+++ b/libc/sysdeps/linux/sh/Makefile
@@ -32,7 +32,7 @@ TARGET_MACHINE_TYPE=$(shell $(CC) -dumpmachine)
CRT0=crt0.S
CRT0_OBJ=$(patsubst %.S,%.o, $(CRT0))
-SSRC=setjmp.S bsd-setjmp.S bsd-_setjmp.S __longjmp.S vfork.S clone.S
+SSRC=setjmp.S __longjmp.S vfork.S clone.S
SOBJS=$(patsubst %.S,%.o, $(SSRC))
CSRC=_mmap.c longjmp.c pipe.c __init_brk.c brk.c sbrk.c
diff --git a/libc/sysdeps/linux/sh/__longjmp.S b/libc/sysdeps/linux/sh/__longjmp.S
index 163801969..7e2b0b16d 100644
--- a/libc/sysdeps/linux/sh/__longjmp.S
+++ b/libc/sysdeps/linux/sh/__longjmp.S
@@ -36,6 +36,21 @@ __longjmp:
mov.l @r4+, r13
mov.l @r4+, r14
mov.l @r4+, r15
+#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__
+ lds.l @r4+, pr
+ ldc.l @r4+, gbr
+ lds.l @r4+, fpscr
+ fmov.s @r4+, fr12
+ fmov.s @r4+, fr13
+ mov r5, r0 /* get the return value in place */
+ tst r0, r0
+ bf.s 1f
+ fmov.s @r4+, fr14
+ mov #1,r0 /* can't let setjmp() return zero! */
+1:
+ rts
+ fmov.s @r4+, fr15
+#else
mov r5, r0 /* get the return value in place */
tst r0, r0
bf.s 1f
@@ -44,5 +59,6 @@ __longjmp:
1:
rts
ldc.l @r4+, gbr
+#endif
.size __longjmp,.-__longjmp;
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;