Initial revision
authorRoland McGrath <roland@gnu.org>
Tue, 15 Nov 1994 10:39:12 +0000 (10:39 +0000)
committerRoland McGrath <roland@gnu.org>
Tue, 15 Nov 1994 10:39:12 +0000 (10:39 +0000)
sysdeps/mach/hurd/alpha/sigreturn.c [new file with mode: 0644]

diff --git a/sysdeps/mach/hurd/alpha/sigreturn.c b/sysdeps/mach/hurd/alpha/sigreturn.c
new file mode 100644 (file)
index 0000000..37f36b6
--- /dev/null
@@ -0,0 +1,222 @@
+/* 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;
+}