From: Roland McGrath Date: Tue, 15 Nov 1994 10:39:12 +0000 (+0000) Subject: Initial revision X-Git-Tag: upstream/2.30~10627^2~4030 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cef89fdba9ac9b35d0666fc5bca905967084823f;p=external%2Fglibc.git Initial revision --- diff --git a/sysdeps/mach/hurd/alpha/sigreturn.c b/sysdeps/mach/hurd/alpha/sigreturn.c new file mode 100644 index 0000000..37f36b6 --- /dev/null +++ b/sysdeps/mach/hurd/alpha/sigreturn.c @@ -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 +#include +#include +#include + +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; +}