1*cb9f529bSchristos /* $NetBSD: __longjmp14.c,v 1.6 2016/01/25 16:44:42 christos Exp $ */
21e1499c7Schs
31e1499c7Schs /*-
41e1499c7Schs * Copyright (c) 2003 The NetBSD Foundation, Inc.
51e1499c7Schs * All rights reserved.
61e1499c7Schs *
71e1499c7Schs * This code is derived from software contributed to The NetBSD Foundation
81e1499c7Schs * by Christian Limpach.
91e1499c7Schs *
101e1499c7Schs * Redistribution and use in source and binary forms, with or without
111e1499c7Schs * modification, are permitted provided that the following conditions
121e1499c7Schs * are met:
131e1499c7Schs * 1. Redistributions of source code must retain the above copyright
141e1499c7Schs * notice, this list of conditions and the following disclaimer.
151e1499c7Schs * 2. Redistributions in binary form must reproduce the above copyright
161e1499c7Schs * notice, this list of conditions and the following disclaimer in the
171e1499c7Schs * documentation and/or other materials provided with the distribution.
181e1499c7Schs *
191e1499c7Schs * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
201e1499c7Schs * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
211e1499c7Schs * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
221e1499c7Schs * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
231e1499c7Schs * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
241e1499c7Schs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
251e1499c7Schs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
261e1499c7Schs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
271e1499c7Schs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
281e1499c7Schs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
291e1499c7Schs * POSSIBILITY OF SUCH DAMAGE.
301e1499c7Schs */
311e1499c7Schs
321e1499c7Schs #include "namespace.h"
331e1499c7Schs #include <sys/types.h>
341e1499c7Schs #include <ucontext.h>
351e1499c7Schs #include <signal.h>
361e1499c7Schs #include <stdlib.h>
371e1499c7Schs #include <string.h>
381e1499c7Schs
391e1499c7Schs #define __LIBC12_SOURCE__
401e1499c7Schs #include <setjmp.h>
41f9efc4abShe #include <compat/include/setjmp.h>
421e1499c7Schs
431e1499c7Schs #include <stdio.h>
441e1499c7Schs #include <unistd.h>
451e1499c7Schs
461e1499c7Schs ssize_t _sys_write(int, void *, size_t);
471e1499c7Schs
481e1499c7Schs void
__longjmp14(jmp_buf env,int val)491e1499c7Schs __longjmp14(jmp_buf env, int val)
501e1499c7Schs {
511e1499c7Schs ucontext_t uc;
521e1499c7Schs struct sigcontext *sc = (void *)env;
53*cb9f529bSchristos __register_t *regs = (void *)(sc + 1);
54*cb9f529bSchristos register __register_t dp __asm("r27");
551e1499c7Schs
561e1499c7Schs /* Ensure non-zero SP */
571e1499c7Schs if (sc->sc_sp == 0)
581e1499c7Schs goto err;
591e1499c7Schs
601e1499c7Schs /* Make return value non-zero */
611e1499c7Schs if (val == 0)
621e1499c7Schs val = 1;
631e1499c7Schs
641e1499c7Schs /* Copy callee-saved regs */
651e1499c7Schs regs -= 3;
661e1499c7Schs uc.uc_mcontext.__gregs[3] = regs[3];
671e1499c7Schs uc.uc_mcontext.__gregs[4] = regs[4];
681e1499c7Schs uc.uc_mcontext.__gregs[5] = regs[5];
691e1499c7Schs uc.uc_mcontext.__gregs[6] = regs[6];
701e1499c7Schs uc.uc_mcontext.__gregs[7] = regs[7];
711e1499c7Schs uc.uc_mcontext.__gregs[8] = regs[8];
721e1499c7Schs uc.uc_mcontext.__gregs[9] = regs[9];
731e1499c7Schs uc.uc_mcontext.__gregs[10] = regs[10];
741e1499c7Schs uc.uc_mcontext.__gregs[11] = regs[11];
751e1499c7Schs uc.uc_mcontext.__gregs[12] = regs[12];
761e1499c7Schs uc.uc_mcontext.__gregs[13] = regs[13];
771e1499c7Schs uc.uc_mcontext.__gregs[14] = regs[14];
781e1499c7Schs uc.uc_mcontext.__gregs[15] = regs[15];
791e1499c7Schs uc.uc_mcontext.__gregs[16] = regs[16];
801e1499c7Schs uc.uc_mcontext.__gregs[17] = regs[17];
811e1499c7Schs uc.uc_mcontext.__gregs[18] = regs[18];
821e1499c7Schs
831e1499c7Schs /* Preserve the current value of DP */
84d66dab05Sskrll /* LINTED dp is r27, so is "initialized" */
851e1499c7Schs uc.uc_mcontext.__gregs[27] = dp;
861e1499c7Schs
871e1499c7Schs /* Set the desired return value. */
881e1499c7Schs uc.uc_mcontext.__gregs[_REG_RET0] = val;
891e1499c7Schs
901e1499c7Schs /*
911e1499c7Schs * Set _UC_{SET,CLR}STACK according to SS_ONSTACK.
921e1499c7Schs *
931e1499c7Schs * Restore the signal mask with sigprocmask() instead of _UC_SIGMASK,
941e1499c7Schs * since libpthread may want to interpose on signal handling.
951e1499c7Schs */
961e1499c7Schs uc.uc_flags = _UC_CPU | (sc->sc_onstack ? _UC_SETSTACK : _UC_CLRSTACK);
971e1499c7Schs
981e1499c7Schs sigprocmask(SIG_SETMASK, &sc->sc_mask, NULL);
991e1499c7Schs
1001e1499c7Schs /* Clear uc_link */
1011e1499c7Schs uc.uc_link = 0;
1021e1499c7Schs
1031e1499c7Schs /* Copy signal mask */
1041e1499c7Schs uc.uc_sigmask = sc->sc_mask;
1051e1499c7Schs
1061e1499c7Schs /* Copy special regs */
1071e1499c7Schs uc.uc_mcontext.__gregs[_REG_PSW] = sc->sc_ps;
1081e1499c7Schs uc.uc_mcontext.__gregs[_REG_SP] = sc->sc_sp;
1091e1499c7Schs uc.uc_mcontext.__gregs[_REG_PCSQH] = sc->sc_pcsqh;
1101e1499c7Schs uc.uc_mcontext.__gregs[_REG_PCOQH] = sc->sc_pcoqh;
1111e1499c7Schs uc.uc_mcontext.__gregs[_REG_PCSQT] = sc->sc_pcsqt;
1121e1499c7Schs uc.uc_mcontext.__gregs[_REG_PCOQT] = sc->sc_pcoqt;
1131e1499c7Schs
1141e1499c7Schs setcontext(&uc);
1151e1499c7Schs err:
1161e1499c7Schs longjmperror();
1171e1499c7Schs abort();
1181e1499c7Schs /* NOTREACHED */
1191e1499c7Schs }
120