Initial revision

This commit is contained in:
Roland McGrath 1994-11-15 10:39:12 +00:00
parent 0044b03ec3
commit cef89fdba9
1 changed files with 222 additions and 0 deletions

View File

@ -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;
}