]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/__longjmp.c
update
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / libc / sysdeps / linux / mips / __longjmp.c
1 /* Copyright (C) 1992, 1995, 1997, 2000 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Brendan Kehoe (brendan@zen.org).
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
18
19 #include <features.h>
20 #include <setjmp.h>
21 #include <stdlib.h>
22 #include <sgidefs.h>
23
24 #ifndef __GNUC__
25   #error This file uses GNU C extensions; you must compile with GCC.
26 #endif
27
28 extern void __longjmp (__jmp_buf __env, int __val) attribute_noreturn;
29 libc_hidden_proto(__longjmp)
30
31 void __longjmp (__jmp_buf env, int val_arg)
32 {
33     /* gcc 1.39.19 miscompiled the longjmp routine (as it did setjmp before
34        the hack around it); force it to use $a1 for the longjmp value.
35        Without this it saves $a1 in a register which gets clobbered
36        along the way.  */
37     register int val __asm__ ("a1");
38
39     /* Pull back the floating point callee-saved registers.  */
40 #if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__
41 #if _MIPS_SIM == _MIPS_SIM_ABI64
42     __asm__ __volatile__ ("l.d $f24, %0" : : "m" (env[0].__fpregs[0]));
43     __asm__ __volatile__ ("l.d $f25, %0" : : "m" (env[0].__fpregs[1]));
44     __asm__ __volatile__ ("l.d $f26, %0" : : "m" (env[0].__fpregs[2]));
45     __asm__ __volatile__ ("l.d $f27, %0" : : "m" (env[0].__fpregs[3]));
46     __asm__ __volatile__ ("l.d $f28, %0" : : "m" (env[0].__fpregs[4]));
47     __asm__ __volatile__ ("l.d $f29, %0" : : "m" (env[0].__fpregs[5]));
48     __asm__ __volatile__ ("l.d $f30, %0" : : "m" (env[0].__fpregs[6]));
49     __asm__ __volatile__ ("l.d $f31, %0" : : "m" (env[0].__fpregs[7]));
50 #else /* O32 || N32 */
51     __asm__ __volatile__ ("l.d $f20, %0" : : "m" (env[0].__fpregs[0]));
52     __asm__ __volatile__ ("l.d $f22, %0" : : "m" (env[0].__fpregs[1]));
53     __asm__ __volatile__ ("l.d $f24, %0" : : "m" (env[0].__fpregs[2]));
54     __asm__ __volatile__ ("l.d $f26, %0" : : "m" (env[0].__fpregs[3]));
55     __asm__ __volatile__ ("l.d $f28, %0" : : "m" (env[0].__fpregs[4]));
56     __asm__ __volatile__ ("l.d $f30, %0" : : "m" (env[0].__fpregs[5]));
57 #endif /* O32 || N32 */
58
59     /* Get and reconstruct the floating point csr.  */
60     __asm__ __volatile__ ("lw $2, %0" : : "m" (env[0].__fpc_csr));
61     __asm__ __volatile__ ("ctc1 $2, $31");
62 #endif
63
64     /* Get the GP. */
65 #if _MIPS_SIM == _MIPS_SIM_ABI64
66     __asm__ __volatile__ ("ld $gp, %0" : : "m" (env[0].__gp));
67 #else /* O32 || N32 */
68     __asm__ __volatile__ ("lw $gp, %0" : : "m" (env[0].__gp));
69 #endif /* O32 || N32 */
70
71     /* Get the callee-saved registers.  */
72 #if _MIPS_SIM == _MIPS_SIM_ABI32
73     __asm__ __volatile__ ("lw $16, %0" : : "m" (env[0].__regs[0]));
74     __asm__ __volatile__ ("lw $17, %0" : : "m" (env[0].__regs[1]));
75     __asm__ __volatile__ ("lw $18, %0" : : "m" (env[0].__regs[2]));
76     __asm__ __volatile__ ("lw $19, %0" : : "m" (env[0].__regs[3]));
77     __asm__ __volatile__ ("lw $20, %0" : : "m" (env[0].__regs[4]));
78     __asm__ __volatile__ ("lw $21, %0" : : "m" (env[0].__regs[5]));
79     __asm__ __volatile__ ("lw $22, %0" : : "m" (env[0].__regs[6]));
80     __asm__ __volatile__ ("lw $23, %0" : : "m" (env[0].__regs[7]));
81 #else /* N32 || N64 */
82     __asm__ __volatile__ ("ld $16, %0" : : "m" (env[0].__regs[0]));
83     __asm__ __volatile__ ("ld $17, %0" : : "m" (env[0].__regs[1]));
84     __asm__ __volatile__ ("ld $18, %0" : : "m" (env[0].__regs[2]));
85     __asm__ __volatile__ ("ld $19, %0" : : "m" (env[0].__regs[3]));
86     __asm__ __volatile__ ("ld $20, %0" : : "m" (env[0].__regs[4]));
87     __asm__ __volatile__ ("ld $21, %0" : : "m" (env[0].__regs[5]));
88     __asm__ __volatile__ ("ld $22, %0" : : "m" (env[0].__regs[6]));
89     __asm__ __volatile__ ("ld $23, %0" : : "m" (env[0].__regs[7]));
90 #endif /* N32 || N64 */
91
92     /* Get the PC.  */
93 #if _MIPS_SIM == _MIPS_SIM_ABI32
94     __asm__ __volatile__ ("lw $25, %0" : : "m" (env[0].__pc));
95 #elif _MIPS_SIM == _MIPS_SIM_NABI32
96     __asm__ __volatile__ ("lw $31, %0" : : "m" (env[0].__pc));
97 #else /* N64 */
98     __asm__ __volatile__ ("ld $31, %0" : : "m" (env[0].__pc));
99 #endif /* N64 */
100
101     /* Restore the stack pointer and the FP.  They have to be restored
102        last and in a single asm as gcc, depending on options used, may
103        use either of them to access env.  */
104 #if _MIPS_SIM == _MIPS_SIM_ABI64
105     __asm__ __volatile__ ("ld $29, %0\n\t"
106             "ld $30, %1\n\t" : : "m" (env[0].__sp), "m" (env[0].__fp));
107 #else /* O32 || N32 */
108     __asm__ __volatile__ ("lw $29, %0\n\t"
109             "lw $30, %1\n\t" : : "m" (env[0].__sp), "m" (env[0].__fp));
110 #endif /* O32 || N32 */
111
112     /* Give setjmp 1 if given a 0, or what they gave us if non-zero.  */
113     if (val == 0)
114         __asm__ __volatile__ ("li $2, 1");
115     else
116         __asm__ __volatile__ ("move $2, %0" : : "r" (val));
117
118 #if _MIPS_SIM == _MIPS_SIM_ABI32
119     __asm__ __volatile__ ("jr $25");
120 #else /* N32 || N64 */
121     __asm__ __volatile__ ("jr $31");
122 #endif /* N32 || N64 */
123
124     /* Avoid `volatile function does return' warnings.  */
125     for (;;);
126 }
127 libc_hidden_def(__longjmp)