From 769814bf89649d8b4f9bd07b36114c8e6e8c446e Mon Sep 17 00:00:00 2001 From: simonb Date: Tue, 23 Mar 2004 02:21:49 +0000 Subject: [PATCH] Use setcontext() instead of sigreturn() to implement longjmp(). --- lib/libc/arch/mips/gen/__longjmp14.c | 105 +++++++++++++++++++++++++++ lib/libc/arch/mips/gen/__setjmp14.S | 23 +----- 2 files changed, 108 insertions(+), 20 deletions(-) create mode 100644 lib/libc/arch/mips/gen/__longjmp14.c diff --git a/lib/libc/arch/mips/gen/__longjmp14.c b/lib/libc/arch/mips/gen/__longjmp14.c new file mode 100644 index 000000000000..bdd1c4bd21cc --- /dev/null +++ b/lib/libc/arch/mips/gen/__longjmp14.c @@ -0,0 +1,105 @@ +/* $NetBSD: __longjmp14.c,v 1.1 2004/03/23 02:21:49 simonb Exp $ */ + +/*- + * Copyright (c) 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christian Limpach and Matt Thomas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "namespace.h" +#include +#include +#include +#include +#include + +#include + +#define __LIBC12_SOURCE__ +#include + +void +__longjmp14(jmp_buf env, int val) +{ + struct sigcontext *sc = (void *)env; + ucontext_t uc; + + /* Ensure non-zero SP and sigcontext magic number is present */ + if (sc->sc_regs[_R_SP] == 0 || sc->sc_regs[_R_ZERO] != 0xACEDBADE) + goto err; + + /* Ensure non-zero return value */ + if (val == 0) + val = 1; + + /* Set _UC_SIGMASK and _UC_CPU */ + uc.uc_flags = _UC_SIGMASK | _UC_CPU; + + /* Clear uc_link */ + uc.uc_link = 0; + + /* Save return value in context */ + uc.uc_mcontext.__gregs[_R_V0] = val; + + /* Copy saved registers */ + uc.uc_mcontext.__gregs[_R_S0] = sc->sc_regs[_R_S0]; + uc.uc_mcontext.__gregs[_R_S1] = sc->sc_regs[_R_S1]; + uc.uc_mcontext.__gregs[_R_S2] = sc->sc_regs[_R_S2]; + uc.uc_mcontext.__gregs[_R_S3] = sc->sc_regs[_R_S3]; + uc.uc_mcontext.__gregs[_R_S4] = sc->sc_regs[_R_S4]; + uc.uc_mcontext.__gregs[_R_S5] = sc->sc_regs[_R_S5]; + uc.uc_mcontext.__gregs[_R_S6] = sc->sc_regs[_R_S6]; + uc.uc_mcontext.__gregs[_R_S7] = sc->sc_regs[_R_S7]; + uc.uc_mcontext.__gregs[_R_S8] = sc->sc_regs[_R_S8]; + uc.uc_mcontext.__gregs[_R_SP] = sc->sc_regs[_R_SP]; + uc.uc_mcontext.__gregs[_R_RA] = sc->sc_regs[_R_RA]; + + /* Copy FP state */ + if (sc->sc_fpused) { + /* FP saved regs are $f20 .. $f31 */ + memcpy(&uc.uc_mcontext.__fpregs.__fp_r. + __fp_regs32.__fp32_regs[20], &sc->sc_fpregs[20], 32 - 20); + uc.uc_mcontext.__fpregs.__fp_csr = sc->sc_regs[_R_FSR]; + /* XXX sc_fp_control */ + uc.uc_flags |= _UC_FPU; + } + + /* Copy signal mask */ + uc.uc_sigmask = sc->sc_mask; + + setcontext(&uc); + err: + longjmperror(); + abort(); + /* NOTREACHED */ +} diff --git a/lib/libc/arch/mips/gen/__setjmp14.S b/lib/libc/arch/mips/gen/__setjmp14.S index 9f4a0816c221..fd283ff05cc2 100644 --- a/lib/libc/arch/mips/gen/__setjmp14.S +++ b/lib/libc/arch/mips/gen/__setjmp14.S @@ -1,4 +1,4 @@ -/* $NetBSD: __setjmp14.S,v 1.9 2003/11/26 08:36:49 he Exp $ */ +/* $NetBSD: __setjmp14.S,v 1.10 2004/03/23 02:21:49 simonb Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -41,7 +41,7 @@ #if defined(LIBC_SCCS) && !defined(lint) ASMSTR("from: @(#)setjmp.s 8.1 (Berkeley) 6/4/93") - ASMSTR("$NetBSD: __setjmp14.S,v 1.9 2003/11/26 08:36:49 he Exp $") + ASMSTR("$NetBSD: __setjmp14.S,v 1.10 2004/03/23 02:21:49 simonb Exp $") #endif /* LIBC_SCCS and not lint */ #ifdef __ABICALLS__ @@ -130,23 +130,6 @@ NON_LEAF(__setjmp14, SETJMP_FRAME_SIZE, ra) move v0, zero j ra REG_EPILOGUE -END(__setjmp14) - -LEAF(__longjmp14) -#ifdef __ABICALLS__ - .set noreorder - .cpload t9 - .set reorder - subu sp, sp, 32 - .cprestore 16 -#endif - REG_PROLOGUE - /* save return value in sc_regs[_R_V0] */ - REG_S a1,(_OFFSETOF_SC_REGS + _R_V0 * SZREG)(a0) - REG_EPILOGUE - li v0, SYS___sigreturn14 - syscall botch: - jal _C_LABEL(longjmperror) jal _C_LABEL(abort) -END(__longjmp14) +END(__setjmp14)