about summary refs log tree commit diff
path: root/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h
diff options
context:
space:
mode:
Diffstat (limited to 'ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h')
-rw-r--r--ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h100
1 files changed, 74 insertions, 26 deletions
diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h b/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h
index 9d949955be..fecd3e433a 100644
--- a/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h
+++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h
@@ -67,25 +67,57 @@
 #undef INTERNAL_SYSCALL_ERRNO
 #define INTERNAL_SYSCALL_ERRNO(val, err)     ((void) (err), val)
 
+/* Note that the original Linux syscall restart convention required the
+   instruction immediately preceding SYSCALL to initialize $v0 with the
+   syscall number.  Then if a restart triggered, $v0 would have been
+   clobbered by the syscall interrupted, and needed to be reinititalized.
+   The kernel would decrement the PC by 4 before switching back to the
+   user mode so that $v0 had been reloaded before SYSCALL was executed
+   again.  This implied the place $v0 was loaded from must have been
+   preserved across a syscall, e.g. an immediate, static register, stack
+   slot, etc.
+
+   The convention was relaxed in Linux with a change applied to the kernel
+   GIT repository as commit 96187fb0bc30cd7919759d371d810e928048249d, that
+   first appeared in the 2.6.36 release.  Since then the kernel has had
+   code that reloads $v0 upon syscall restart and resumes right at the
+   SYSCALL instruction, so no special arrangement is needed anymore.
+
+   For backwards compatibility with existing kernel binaries we support
+   the old convention by choosing the instruction preceding SYSCALL
+   carefully.  This also means we have to force a 32-bit encoding of the
+   microMIPS MOVE instruction if one is used.  */
+
+#ifdef __mips_micromips
+# define MOVE32 "move32"
+#else
+# define MOVE32 "move"
+#endif
+
 #undef INTERNAL_SYSCALL
-#define INTERNAL_SYSCALL(name, err, nr, args...) \
-	internal_syscall##nr (, "li\t$2, %2\t\t\t# " #name "\n\t",	\
-			      "i" (SYS_ify (name)), err, args)
+#define INTERNAL_SYSCALL(name, err, nr, args...)			\
+	internal_syscall##nr ("li\t%0, %2\t\t\t# " #name "\n\t",	\
+			      "IK" (SYS_ify (name)),			\
+			      0, err, args)
 
 #undef INTERNAL_SYSCALL_NCS
-#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
-	internal_syscall##nr (= number, , "r" (__v0), err, args)
+#define INTERNAL_SYSCALL_NCS(number, err, nr, args...)			\
+	internal_syscall##nr (MOVE32 "\t%0, %2\n\t",			\
+			      "r" (__s0),				\
+			      number, err, args)
 
-#define internal_syscall0(ncs_init, cs_init, input, err, dummy...)	\
+#define internal_syscall0(v0_init, input, number, err, dummy...)	\
 ({									\
 	long _sys_result;						\
 									\
 	{								\
-	register long __v0 asm("$2") ncs_init;				\
+	register long __s0 asm("$16") __attribute__ ((unused))		\
+	  = (number);							\
+	register long __v0 asm("$2");					\
 	register long __a3 asm("$7");					\
 	__asm__ volatile (						\
 	".set\tnoreorder\n\t"						\
-	cs_init								\
+	v0_init								\
 	"syscall\n\t"							\
 	".set reorder"							\
 	: "=r" (__v0), "=r" (__a3)					\
@@ -97,17 +129,19 @@
 	_sys_result;							\
 })
 
-#define internal_syscall1(ncs_init, cs_init, input, err, arg1)		\
+#define internal_syscall1(v0_init, input, number, err, arg1)		\
 ({									\
 	long _sys_result;						\
 									\
 	{								\
-	register long __v0 asm("$2") ncs_init;				\
+	register long __s0 asm("$16") __attribute__ ((unused))		\
+	  = (number);							\
+	register long __v0 asm("$2");					\
 	register long __a0 asm("$4") = (long) (arg1);			\
 	register long __a3 asm("$7");					\
 	__asm__ volatile (						\
 	".set\tnoreorder\n\t"						\
-	cs_init								\
+	v0_init								\
 	"syscall\n\t"							\
 	".set reorder"							\
 	: "=r" (__v0), "=r" (__a3)					\
@@ -119,18 +153,20 @@
 	_sys_result;							\
 })
 
-#define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2)	\
+#define internal_syscall2(v0_init, input, number, err, arg1, arg2)	\
 ({									\
 	long _sys_result;						\
 									\
 	{								\
-	register long __v0 asm("$2") ncs_init;				\
+	register long __s0 asm("$16") __attribute__ ((unused))		\
+	  = (number);							\
+	register long __v0 asm("$2");					\
 	register long __a0 asm("$4") = (long) (arg1);			\
 	register long __a1 asm("$5") = (long) (arg2);			\
 	register long __a3 asm("$7");					\
 	__asm__ volatile (						\
 	".set\tnoreorder\n\t"						\
-	cs_init								\
+	v0_init								\
 	"syscall\n\t"							\
 	".set\treorder"							\
 	: "=r" (__v0), "=r" (__a3)					\
@@ -142,19 +178,22 @@
 	_sys_result;							\
 })
 
-#define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3) \
+#define internal_syscall3(v0_init, input, number, err,			\
+			  arg1, arg2, arg3)				\
 ({									\
 	long _sys_result;						\
 									\
 	{								\
-	register long __v0 asm("$2") ncs_init;				\
+	register long __s0 asm("$16") __attribute__ ((unused))		\
+	  = (number);							\
+	register long __v0 asm("$2");					\
 	register long __a0 asm("$4") = (long) (arg1);			\
 	register long __a1 asm("$5") = (long) (arg2);			\
 	register long __a2 asm("$6") = (long) (arg3);			\
 	register long __a3 asm("$7");					\
 	__asm__ volatile (						\
 	".set\tnoreorder\n\t"						\
-	cs_init								\
+	v0_init								\
 	"syscall\n\t"							\
 	".set\treorder"							\
 	: "=r" (__v0), "=r" (__a3)					\
@@ -166,19 +205,22 @@
 	_sys_result;							\
 })
 
-#define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4) \
+#define internal_syscall4(v0_init, input, number, err,			\
+			  arg1, arg2, arg3, arg4)			\
 ({									\
 	long _sys_result;						\
 									\
 	{								\
-	register long __v0 asm("$2") ncs_init;				\
+	register long __s0 asm("$16") __attribute__ ((unused))		\
+	  = (number);							\
+	register long __v0 asm("$2");					\
 	register long __a0 asm("$4") = (long) (arg1);			\
 	register long __a1 asm("$5") = (long) (arg2);			\
 	register long __a2 asm("$6") = (long) (arg3);			\
 	register long __a3 asm("$7") = (long) (arg4);			\
 	__asm__ volatile (						\
 	".set\tnoreorder\n\t"						\
-	cs_init								\
+	v0_init								\
 	"syscall\n\t"							\
 	".set\treorder"							\
 	: "=r" (__v0), "+r" (__a3)					\
@@ -190,12 +232,15 @@
 	_sys_result;							\
 })
 
-#define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5) \
+#define internal_syscall5(v0_init, input, number, err,			\
+			  arg1, arg2, arg3, arg4, arg5)			\
 ({									\
 	long _sys_result;						\
 									\
 	{								\
-	register long __v0 asm("$2") ncs_init;				\
+	register long __s0 asm("$16") __attribute__ ((unused))		\
+	  = (number);							\
+	register long __v0 asm("$2");					\
 	register long __a0 asm("$4") = (long) (arg1);			\
 	register long __a1 asm("$5") = (long) (arg2);			\
 	register long __a2 asm("$6") = (long) (arg3);			\
@@ -203,7 +248,7 @@
 	register long __a4 asm("$8") = (long) (arg5);			\
 	__asm__ volatile (						\
 	".set\tnoreorder\n\t"						\
-	cs_init								\
+	v0_init								\
 	"syscall\n\t"							\
 	".set\treorder"							\
 	: "=r" (__v0), "+r" (__a3)					\
@@ -215,12 +260,15 @@
 	_sys_result;							\
 })
 
-#define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6) \
+#define internal_syscall6(v0_init, input, number, err,			\
+			  arg1, arg2, arg3, arg4, arg5, arg6)		\
 ({									\
 	long _sys_result;						\
 									\
 	{								\
-	register long __v0 asm("$2") ncs_init;				\
+	register long __s0 asm("$16") __attribute__ ((unused))		\
+	  = (number);							\
+	register long __v0 asm("$2");					\
 	register long __a0 asm("$4") = (long) (arg1);			\
 	register long __a1 asm("$5") = (long) (arg2);			\
 	register long __a2 asm("$6") = (long) (arg3);			\
@@ -229,7 +277,7 @@
 	register long __a5 asm("$9") = (long) (arg6);			\
 	__asm__ volatile (						\
 	".set\tnoreorder\n\t"						\
-	cs_init								\
+	v0_init								\
 	"syscall\n\t"							\
 	".set\treorder"							\
 	: "=r" (__v0), "+r" (__a3)					\