mips: use PTRACE_GETREGS to fetch all registers

* linux/mips/arch_regs.h (struct mips_regs): New structure.
(mips_REG_*): New macros.
* signal.c (sys_sigreturn) [MIPS]: Use mips_REG_SP.
* syscall.c [MIPS] (struct mips_regs): New variable.
[MIPS] (ARCH_REGS_FOR_GETREGS): New macro.
(mips_a3, mips_r2): Remove.
(print_pc) [MIPS]: Use mips_REG_EPC.
(get_scno) [MIPS]: Use mips_REG_V0 and mips_REG_A3.
(get_syscall_args) [MIPS]: Use mips_REG_A[0-5].
(get_syscall_result) [MIPS]: Remove.
(get_error) [MIPS]: Use mips_REG_A3 and mips_REG_V0.
diff --git a/linux/mips/arch_regs.h b/linux/mips/arch_regs.h
index 59039c6..6372bad 100644
--- a/linux/mips/arch_regs.h
+++ b/linux/mips/arch_regs.h
@@ -1,5 +1,18 @@
+struct mips_regs {
+	uint64_t uregs[38];
+};
+
+extern struct mips_regs mips_regs;
+
 #define REG_V0 2
 #define REG_A0 4
-#define REG_A3 7
-#define REG_SP 29
-#define REG_EPC 64
+
+#define mips_REG_V0 mips_regs.uregs[REG_V0]
+#define mips_REG_A0 mips_regs.uregs[REG_A0 + 0]
+#define mips_REG_A1 mips_regs.uregs[REG_A0 + 1]
+#define mips_REG_A2 mips_regs.uregs[REG_A0 + 2]
+#define mips_REG_A3 mips_regs.uregs[REG_A0 + 3]
+#define mips_REG_A4 mips_regs.uregs[REG_A0 + 4]
+#define mips_REG_A5 mips_regs.uregs[REG_A0 + 5]
+#define mips_REG_SP mips_regs.uregs[29]
+#define mips_REG_EPC mips_regs.uregs[34]
diff --git a/signal.c b/signal.c
index b1a486a..d877c0a 100644
--- a/signal.c
+++ b/signal.c
@@ -866,27 +866,17 @@
 	/* This decodes rt_sigreturn.  The 64-bit ABIs do not have
 	   sigreturn.  */
 	if (entering(tcp)) {
-		long sp;
 		struct ucontext uc;
-		if (upeek(tcp->pid, REG_SP, &sp) < 0)
-			return 0;
 		/* There are six words followed by a 128-byte siginfo.  */
-		sp = sp + 6 * 4 + 128;
+		long sp = mips_REG_SP + 6 * 4 + 128;
 		if (umove(tcp, sp, &uc) < 0)
 			return 0;
 		tprintsigmask_val(") (mask ", uc.uc_sigmask);
 	}
-#elif defined(MIPS)
+#elif defined(LINUX_MIPSO32)
 	if (entering(tcp)) {
-		long sp;
-		struct pt_regs regs;
 		m_siginfo_t si;
-		if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
-			perror_msg("sigreturn: PTRACE_GETREGS");
-			return 0;
-		}
-		sp = regs.regs[29];
-		if (umove(tcp, sp, &si) < 0)
+		if (umove(tcp, mips_REG_SP, &si) < 0)
 			return 0;
 		tprintsigmask_val(") (mask ", si.si_mask);
 	}
diff --git a/syscall.c b/syscall.c
index 5e1e021..29aa6d1 100644
--- a/syscall.c
+++ b/syscall.c
@@ -756,12 +756,10 @@
 #elif defined(SPARC) || defined(SPARC64)
 struct pt_regs sparc_regs; /* not static */
 # define ARCH_REGS_FOR_GETREGS sparc_regs
-#elif defined(LINUX_MIPSN32)
-static long long mips_a3;
-static long long mips_r2;
 #elif defined(MIPS)
-static long mips_a3;
-static long mips_r2;
+struct mips_regs mips_regs; /* not static */
+/* PTRACE_GETREGS on MIPS is available since linux v2.6.15. */
+# define ARCH_REGS_FOR_GETREGS mips_regs
 #elif defined(S390) || defined(S390X)
 static long s390_gpr2;
 #elif defined(HPPA)
@@ -865,13 +863,10 @@
 		return;
 	}
 	tprintf("[%08lx] ", pc);
-#elif defined(MIPS)
-	long pc;
-	if (upeek(tcp->pid, REG_EPC, &pc) < 0) {
-		tprints("[????????] ");
-		return;
-	}
-	tprintf("[%08lx] ", pc);
+#elif defined LINUX_MIPSN64
+	tprintf("[%016lx] ", mips_REG_EPC);
+#elif defined MIPS
+	tprintf("[%08lx] ", (unsigned long) mips_REG_EPC);
 #elif defined(SH)
 	long pc;
 	if (upeek(tcp->pid, 4*REG_PC, &pc) < 0) {
@@ -1406,30 +1401,11 @@
 #elif defined(M68K)
 	if (upeek(tcp->pid, 4*PT_ORIG_D0, &scno) < 0)
 		return -1;
-#elif defined(LINUX_MIPSN32)
-	unsigned long long regs[38];
-
-	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
-		return -1;
-	mips_a3 = regs[REG_A3];
-	mips_r2 = regs[REG_V0];
-
-	scno = mips_r2;
-	if (!SCNO_IN_RANGE(scno)) {
-		if (mips_a3 == 0 || mips_a3 == -1) {
-			if (debug_flag)
-				fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
-			return 0;
-		}
-	}
 #elif defined(MIPS)
-	if (upeek(tcp->pid, REG_A3, &mips_a3) < 0)
-		return -1;
-	if (upeek(tcp->pid, REG_V0, &scno) < 0)
-		return -1;
+	scno = mips_REG_V0;
 
 	if (!SCNO_IN_RANGE(scno)) {
-		if (mips_a3 == 0 || mips_a3 == -1) {
+		if (mips_REG_A3 == 0 || mips_REG_A3 == -1) {
 			if (debug_flag)
 				fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
 			return 0;
@@ -1858,34 +1834,35 @@
 			tcp->u_arg[i] &= 0xffffffff;
 		}
 	}
-#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
-	/* N32 and N64 both use up to six registers.  */
-	unsigned long long regs[38];
-
-	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
-		return -1;
-
-	for (i = 0; i < nargs; ++i) {
-		tcp->u_arg[i] = regs[REG_A0 + i];
-# if defined(LINUX_MIPSN32)
-		tcp->ext_arg[i] = regs[REG_A0 + i];
-# endif
-	}
-#elif defined(MIPS)
+#elif defined LINUX_MIPSN64
+	(void)i;
+	(void)nargs;
+	tcp->u_arg[0] = mips_REG_A0;
+	tcp->u_arg[1] = mips_REG_A1;
+	tcp->u_arg[2] = mips_REG_A2;
+	tcp->u_arg[3] = mips_REG_A3;
+	tcp->u_arg[4] = mips_REG_A4;
+	tcp->u_arg[5] = mips_REG_A5;
+#elif defined LINUX_MIPSN32
+	(void)i;
+	(void)nargs;
+	tcp->u_arg[0] = tcp->ext_arg[0] = mips_REG_A0;
+	tcp->u_arg[1] = tcp->ext_arg[1] = mips_REG_A1;
+	tcp->u_arg[2] = tcp->ext_arg[2] = mips_REG_A2;
+	tcp->u_arg[3] = tcp->ext_arg[3] = mips_REG_A3;
+	tcp->u_arg[4] = tcp->ext_arg[4] = mips_REG_A4;
+	tcp->u_arg[5] = tcp->ext_arg[5] = mips_REG_A5;
+#elif defined LINUX_MIPSO32
+	(void)i;
+	(void)nargs;
+	tcp->u_arg[0] = mips_REG_A0;
+	tcp->u_arg[1] = mips_REG_A1;
+	tcp->u_arg[2] = mips_REG_A2;
+	tcp->u_arg[3] = mips_REG_A3;
 	if (nargs > 4) {
-		long sp;
-
-		if (upeek(tcp->pid, REG_SP, &sp) < 0)
-			return -1;
-		for (i = 0; i < 4; ++i)
-			if (upeek(tcp->pid, REG_A0 + i, &tcp->u_arg[i]) < 0)
-				return -1;
-		umoven(tcp, sp + 16, (nargs - 4) * sizeof(tcp->u_arg[0]),
+		umoven(tcp, mips_REG_SP + 4 * 4,
+		       (nargs - 4) * sizeof(tcp->u_arg[0]),
 		       (char *)(tcp->u_arg + 4));
-	} else {
-		for (i = 0; i < nargs; ++i)
-			if (upeek(tcp->pid, REG_A0 + i, &tcp->u_arg[i]) < 0)
-				return -1;
 	}
 #elif defined(POWERPC)
 	(void)i;
@@ -2168,18 +2145,6 @@
 #elif defined(M68K)
 	if (upeek(tcp->pid, 4*PT_D0, &m68k_d0) < 0)
 		return -1;
-#elif defined(LINUX_MIPSN32)
-	unsigned long long regs[38];
-
-	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
-		return -1;
-	mips_a3 = regs[REG_A3];
-	mips_r2 = regs[REG_V0];
-#elif defined(MIPS)
-	if (upeek(tcp->pid, REG_A3, &mips_a3) < 0)
-		return -1;
-	if (upeek(tcp->pid, REG_V0, &mips_r2) < 0)
-		return -1;
 #elif defined(ALPHA)
 	if (upeek(tcp->pid, REG_A3, &alpha_a3) < 0)
 		return -1;
@@ -2302,14 +2267,14 @@
 		}
 	}
 #elif defined(MIPS)
-	if (check_errno && mips_a3) {
+	if (check_errno && mips_REG_A3) {
 		tcp->u_rval = -1;
-		u_error = mips_r2;
+		u_error = mips_REG_V0;
 	} else {
-		tcp->u_rval = mips_r2;
-# if defined(LINUX_MIPSN32)
-		tcp->u_lrval = mips_r2;
+# if defined LINUX_MIPSN32
+		tcp->u_lrval = mips_REG_V0;
 # endif
+		tcp->u_rval = mips_REG_V0;
 	}
 #elif defined(POWERPC)
 	if (check_errno && (ppc_regs.ccr & 0x10000000)) {