From b8f04323dc64d1221e5fb3f1162bd6a5aea81912 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Wed, 3 Aug 1994 06:45:59 +0000 Subject: [PATCH] Compare *reply_port to MACH_PORT_NULL, not implicit zero. (restore_gpr): Use N-1 as subscript into sc_gpr (sc_gpr[0] => $1). Before general regs, restore from sc_mdlo and sc_mdhi. Don't treat sp, fp specially; use restore_gpr for them too. For final return, store user $1 value beyond top of user stack ahead of time; Then use $1 to hold the user PC, and restore it from the stack in the delay slot. --- sysdeps/mach/hurd/mips/sigreturn.c | 42 +++++++++++++++++------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/sysdeps/mach/hurd/mips/sigreturn.c b/sysdeps/mach/hurd/mips/sigreturn.c index 147243f5b9..8082acaf9b 100644 --- a/sysdeps/mach/hurd/mips/sigreturn.c +++ b/sysdeps/mach/hurd/mips/sigreturn.c @@ -16,8 +16,6 @@ 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. */ -register int sp asm ("$29"), fp asm ("$30"); - #include #include #include @@ -45,19 +43,31 @@ __sigreturn (const struct sigcontext *scp) reply port in use by the thread when interrupted. */ reply_port = (mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY); - if (*reply_port) + if (*reply_port != MACH_PORT_NULL) __mach_port_destroy (__mach_task_self (), *reply_port); *reply_port = scp->sc_reply_port; - /* Restore registers. */ + /* Load all the registers from the sigcontext. */ #define restore_gpr(n) \ - asm volatile ("lw $" #n ",%0" : : "m" (scpreg->sc_gpr[n])) + asm volatile ("lw $" #n ",%0" : : "m" (scpreg->sc_gpr[n - 1])) - asm volatile (".set noreorder; .set noat;"); { register const struct sigcontext *const scpreg asm ("$1") = scp; - /* Load the general-purpose registers from the sigcontext. */ + /* Just beyond the top of the user stack, store the user's value for $1 + (which we are using for SCPREG). We restore this register as the + very last thing, below. */ + ((int *) scpreg->sc_gpr[29 - 1])[-1] = scpreg->sc_gpr[0]; + + /* First restore the multiplication result registers. The compiler + will use some temporary registers, so we do this before restoring + the general registers. */ + asm volatile ("mtlo %0" : : "r" (scpreg->sc_mdlo)); + asm volatile ("mthi %0" : : "r" (scpreg->sc_mdhi)); + + asm volatile (".set noreorder; .set noat;"); + + /* Restore the normal registers. */ restore_gpr (2); restore_gpr (3); restore_gpr (4); @@ -84,20 +94,16 @@ __sigreturn (const struct sigcontext *scp) restore_gpr (25); /* Registers 26-27 are kernel-only. */ restore_gpr (28); - - /* Now the special-purpose registers. */ - sp = scpreg->sc_sp; /* Stack pointer. */ - fp = scpreg->sc_fp; /* Frame pointer. */ + restore_gpr (29); /* Stack pointer. */ + restore_gpr (30); /* Frame pointer. */ restore_gpr (31); /* Return address. */ /* Now jump to the saved PC. */ - asm volatile ("lw $24, %0\n" /* Load saved PC into temporary $t8. */ - "j $24\n" /* Jump to the saved PC value. */ - "lw $1, %1\n" /* Restore $at in delay slot. */ - : : - "m" (scpreg->sc_pc), - "m" (scpreg->sc_r1) /* $at */ - : "$24"); /* XXX clobbers $24 (aka $t8)!! */ + asm volatile ("lw $1, %0\n" /* Load saved PC into $1. */ + "j $1\n" /* Jump to the saved PC value. */ + "lw $1, -4(sp)\n" /* Restore $1 from stack in delay slot. */ + : : "m" (scpreg->sc_pc)); + asm volatile (".set reorder; .set at;"); } -- 2.43.5