1 /* $NetBSD: longjmp.c,v 1.4 2010/09/03 17:22:51 matt Exp $ */
4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christian Limpach and Matt Thomas.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include "namespace.h"
33 #include <sys/types.h>
39 #include <machine/regnum.h>
41 #define __LIBC12_SOURCE__
43 #include <compat/include/setjmp.h>
46 __longjmp14(jmp_buf env
, int val
)
48 struct sigcontext
*sc
= (void *)env
;
51 /* Ensure non-zero SP and sigcontext magic number is present */
52 if (sc
->sc_regs
[_R_SP
] == 0 || sc
->sc_regs
[_R_ZERO
] != (mips_reg_t
)0xACEDBADE)
55 /* Ensure non-zero return value */
60 * Set _UC_{SET,CLR}STACK according to SS_ONSTACK.
62 * Restore the signal mask with sigprocmask() instead of _UC_SIGMASK,
63 * since libpthread may want to interpose on signal handling.
65 uc
.uc_flags
= _UC_CPU
| (sc
->sc_onstack
? _UC_SETSTACK
: _UC_CLRSTACK
);
67 sigprocmask(SIG_SETMASK
, &sc
->sc_mask
, NULL
);
72 /* Save return value in context */
73 uc
.uc_mcontext
.__gregs
[_REG_V0
] = val
;
75 /* Copy saved registers */
76 uc
.uc_mcontext
.__gregs
[_REG_S0
] = sc
->sc_regs
[_R_S0
];
77 uc
.uc_mcontext
.__gregs
[_REG_S1
] = sc
->sc_regs
[_R_S1
];
78 uc
.uc_mcontext
.__gregs
[_REG_S2
] = sc
->sc_regs
[_R_S2
];
79 uc
.uc_mcontext
.__gregs
[_REG_S3
] = sc
->sc_regs
[_R_S3
];
80 uc
.uc_mcontext
.__gregs
[_REG_S4
] = sc
->sc_regs
[_R_S4
];
81 uc
.uc_mcontext
.__gregs
[_REG_S5
] = sc
->sc_regs
[_R_S5
];
82 uc
.uc_mcontext
.__gregs
[_REG_S6
] = sc
->sc_regs
[_R_S6
];
83 uc
.uc_mcontext
.__gregs
[_REG_S7
] = sc
->sc_regs
[_R_S7
];
84 uc
.uc_mcontext
.__gregs
[_REG_S8
] = sc
->sc_regs
[_R_S8
];
85 #if defined(__mips_n32) || defined(__mips_n64)
86 uc
.uc_mcontext
.__gregs
[_REG_GP
] = sc
->sc_regs
[_R_GP
];
88 uc
.uc_mcontext
.__gregs
[_REG_SP
] = sc
->sc_regs
[_R_SP
];
89 uc
.uc_mcontext
.__gregs
[_REG_RA
] = sc
->sc_regs
[_R_RA
];
90 uc
.uc_mcontext
.__gregs
[_REG_EPC
] = sc
->sc_pc
;
94 /* FP saved regs are $f20 .. $f31 */
95 memcpy(&uc
.uc_mcontext
.__fpregs
.__fp_r
.__fp_regs
[20],
96 &sc
->sc_fpregs
[20], 32 - 20);
97 uc
.uc_mcontext
.__fpregs
.__fp_csr
=
98 sc
->sc_fpregs
[_R_FSR
- _FPBASE
];
99 /* XXX sc_fp_control */
100 uc
.uc_flags
|= _UC_FPU
;