--- /dev/null
+/* Return from signal handler in GNU C library for Hurd. Alpha version.
+Copyright (C) 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* Declare global register variables before any code. */
+register double f0 asm ("$f0");
+register double f1 asm ("$f1");
+register double f2 asm ("$f2");
+register double f3 asm ("$f3");
+register double f4 asm ("$f4");
+register double f5 asm ("$f5");
+register double f6 asm ("$f6");
+register double f7 asm ("$f7");
+register double f8 asm ("$f8");
+register double f9 asm ("$f9");
+register double f10 asm ("$f10");
+register double f11 asm ("$f11");
+register double f12 asm ("$f12");
+register double f13 asm ("$f13");
+register double f14 asm ("$f14");
+register double f15 asm ("$f15");
+register double f16 asm ("$f16");
+register double f17 asm ("$f17");
+register double f18 asm ("$f18");
+register double f19 asm ("$f19");
+register double f20 asm ("$f20");
+register double f21 asm ("$f21");
+register double f22 asm ("$f22");
+register double f23 asm ("$f23");
+register double f24 asm ("$f24");
+register double f25 asm ("$f25");
+register double f26 asm ("$f26");
+register double f27 asm ("$f27");
+register double f28 asm ("$f28");
+register double f29 asm ("$f29");
+register double f30 asm ("$f30");;
+
+#include <hurd.h>
+#include <hurd/signal.h>
+#include <hurd/threadvar.h>
+#include <stdlib.h>
+
+int
+__sigreturn (struct sigcontext *scp)
+{
+ struct hurd_sigstate *ss;
+ mach_port_t *reply_port;
+
+ if (scp == NULL || (scp->sc_mask & _SIG_CANT_MASK))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ ss = _hurd_self_sigstate (); /* SS->lock now locked. */
+
+ /* Restore the set of blocked signals, and the intr_port slot. */
+ ss->blocked = scp->sc_mask;
+ ss->intr_port = scp->sc_intr_port;
+
+ /* Check for pending signals that were blocked by the old set. */
+ if (ss->pending & ~ss->blocked)
+ {
+ /* There are pending signals that just became unblocked. Wake up the
+ signal thread to deliver them. But first, squirrel away SCP where
+ the signal thread will notice it if it runs another handler, and
+ arrange to have us called over again in the new reality. */
+ ss->context = scp;
+ /* Clear the intr_port slot, since we are not in fact doing
+ an interruptible RPC right now. If SS->intr_port is not null,
+ the SCP context is doing an interruptible RPC, but the signal
+ thread will examine us while we are blocked in the sig_post RPC. */
+ ss->intr_port = MACH_PORT_NULL;
+ __mutex_unlock (&ss->lock);
+ __sig_post (_hurd_msgport, 0, __mach_task_self ());
+ /* If a pending signal was handled, sig_post never returned. */
+ __mutex_lock (&ss->lock);
+ }
+
+ if (scp->sc_onstack)
+ {
+ ss->sigaltstack.ss_flags &= ~SA_ONSTACK; /* XXX threadvars */
+ /* XXX cannot unlock until off sigstack */
+ abort ();
+ }
+ else
+ __mutex_unlock (&ss->lock);
+
+ /* Destroy the MiG reply port used by the signal handler, and restore the
+ reply port in use by the thread when interrupted. */
+ reply_port =
+ (mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY);
+ if (*reply_port)
+ __mach_port_destroy (__mach_task_self (), *reply_port);
+ *reply_port = scp->sc_reply_port;
+
+ if (scp->sc_used_fpa)
+ {
+ /* Restore FPU state. */
+
+ /* Restore the floating-point control/status register.
+ We must do this first because the compiler will need
+ a temporary FP register for the load. */
+ asm volatile ("mt_fpcr %0" : : "f" (scp->sc_fpcsr));
+
+ /* Restore floating-point registers. */
+ f0 = scp->sc_fpregs[0];
+ f1 = scp->sc_fpregs[1];
+ f2 = scp->sc_fpregs[2];
+ f3 = scp->sc_fpregs[3];
+ f4 = scp->sc_fpregs[4];
+ f5 = scp->sc_fpregs[5];
+ f6 = scp->sc_fpregs[6];
+ f7 = scp->sc_fpregs[7];
+ f8 = scp->sc_fpregs[8];
+ f9 = scp->sc_fpregs[9];
+ f10 = scp->sc_fpregs[10];
+ f11 = scp->sc_fpregs[11];
+ f12 = scp->sc_fpregs[12];
+ f13 = scp->sc_fpregs[13];
+ f14 = scp->sc_fpregs[14];
+ f15 = scp->sc_fpregs[15];
+ f16 = scp->sc_fpregs[16];
+ f17 = scp->sc_fpregs[17];
+ f18 = scp->sc_fpregs[18];
+ f19 = scp->sc_fpregs[19];
+ f20 = scp->sc_fpregs[20];
+ f21 = scp->sc_fpregs[21];
+ f22 = scp->sc_fpregs[22];
+ f23 = scp->sc_fpregs[23];
+ f24 = scp->sc_fpregs[24];
+ f25 = scp->sc_fpregs[25];
+ f26 = scp->sc_fpregs[26];
+ f27 = scp->sc_fpregs[27];
+ f28 = scp->sc_fpregs[28];
+ f29 = scp->sc_fpregs[29];
+ f30 = scp->sc_fpregs[30];
+ }
+
+ /* Load all the registers from the sigcontext. */
+#define restore_gpr(n) \
+ asm volatile ("ldq $" #n ",%0" : : "m" (scpreg->sc_gpr[n]))
+
+ {
+ /* The `rei' PAL pseudo-instruction restores registers $2..$7,
+ the PC and processor status. So we can use these few registers
+ for our working variables. */
+ register const struct sigcontext *const scpreg asm ("$2") = scp;
+ register long int *sp asm ("$30");
+
+ asm volatile (".set noreorder; .set noat;");
+
+ /* Restore the other general registers. */
+ restore_gpr (1);
+ restore_gpr (8);
+ restore_gpr (9);
+ restore_gpr (10);
+ restore_gpr (11);
+ restore_gpr (12);
+ restore_gpr (13);
+ restore_gpr (14);
+ restore_gpr (15);
+ restore_gpr (16);
+ restore_gpr (17);
+ restore_gpr (18);
+ restore_gpr (19);
+ restore_gpr (20);
+ restore_gpr (21);
+ restore_gpr (22);
+ restore_gpr (23);
+ restore_gpr (24);
+ restore_gpr (25);
+ restore_gpr (26);
+ restore_gpr (27);
+ restore_gpr (28);
+ restore_gpr (29);
+ restore_gpr (30); /* Stack pointer. */
+
+ /* The magical `rei' instruction looks at the SP ($30) for:
+
+ sp--> t1 ($2)
+ +0x8 t2 ($3)
+ +0x10 t3 ($4)
+ +0x18 t4 ($5)
+ +0x20 t5 ($6)
+ +0x28 t6 ($7)
+ +0x30 PC
+ +0x38 PS
+
+ For the first six words, &scp->sc_regs[2] already looks like this.
+ So we clobber the following words words where $8 and $9 were saved
+ (we already restored them above) with the PC and PS to be restored,
+ and then point the SP there. */
+
+ scpreg->sc_regs[8] = scpreg->sc_pc;
+ /* scpreg->sc_regs[9] = scpreg->sc_ps; XXX where to get it from??? */
+
+ /* XXX What will restore the user's SP??? */
+ sp = &scpreg->sc_regs[2];
+ asm volatile ("call_pal %0" : : "i" (op_rei));
+
+ asm volatile (".set reorder; .set at;");
+ }
+
+ /* NOTREACHED */
+ return -1;
+}