Rename variable AT (which is the register's name) to SCPREG.
[kopensolaris-gnu/glibc.git] / sysdeps / mach / hurd / mips / sigreturn.c
1 /* Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB.  If
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA.  */
18
19 register int sp asm ("$29"), fp asm ("$30");
20
21 #include <hurd.h>
22 #include <hurd/signal.h>
23 #include <hurd/threadvar.h>
24
25 int
26 __sigreturn (const struct sigcontext *scp)
27 {
28   struct hurd_sigstate *ss;
29   mach_port_t *reply_port;
30
31   if (scp == NULL)
32     {
33       errno = EINVAL;
34       return -1;
35     }
36
37   ss = _hurd_self_sigstate ();
38   ss->blocked = scp->sc_mask;
39   ss->intr_port = scp->sc_intr_port;
40   if (scp->sc_onstack)
41     ss->sigaltstack.ss_flags &= ~SA_ONSTACK; /* XXX threadvars */
42   __mutex_unlock (&ss->lock);
43
44   /* Destroy the MiG reply port used by the signal handler, and restore the
45      reply port in use by the thread when interrupted.  */
46   reply_port =
47     (mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY);
48   if (*reply_port)
49     __mach_port_destroy (__mach_task_self (), *reply_port);
50   *reply_port = scp->sc_reply_port;
51
52   /* Restore registers.  */
53 #define restore_gpr(n) \
54   asm volatile ("lw $" #n ",%0" : : "m" (scpreg->sc_gpr[n]))
55
56   asm volatile (".set noreorder; .set noat;");
57   {
58     register const struct sigcontext *const scpreg asm ("$1") = scp;
59
60     /* Load the general-purpose registers from the sigcontext.  */
61     restore_gpr (2);
62     restore_gpr (3);
63     restore_gpr (4);
64     restore_gpr (5);
65     restore_gpr (6);
66     restore_gpr (7);
67     restore_gpr (8);
68     restore_gpr (9);
69     restore_gpr (10);
70     restore_gpr (11);
71     restore_gpr (12);
72     restore_gpr (13);
73     restore_gpr (14);
74     restore_gpr (15);
75     restore_gpr (16);
76     restore_gpr (17);
77     restore_gpr (18);
78     restore_gpr (19);
79     restore_gpr (20);
80     restore_gpr (21);
81     restore_gpr (22);
82     restore_gpr (23);
83     restore_gpr (24);
84     restore_gpr (25);
85     /* Registers 26-27 are kernel-only.  */
86     restore_gpr (28);
87
88     /* Now the special-purpose registers.  */
89     sp = scpreg->sc_sp;         /* Stack pointer.  */
90     fp = scpreg->sc_fp;         /* Frame pointer.  */
91     restore_gpr (31);           /* Return address.  */
92
93     /* Now jump to the saved PC.  */
94     asm volatile ("lw $24, %0\n" /* Load saved PC into temporary $t8.  */
95                   "j $24\n"     /* Jump to the saved PC value.  */
96                   "lw $1, %1\n" /* Restore $at in delay slot.  */
97                   : :
98                   "m" (scpreg->sc_pc),
99                   "m" (scpreg->sc_r1) /* $at */
100                   : "$24");     /* XXX clobbers $24 (aka $t8)!! */
101     asm volatile (".set reorder; .set at;");
102   }
103
104   /* NOTREACHED */
105   return -1;
106 }