2003-07-28  Daniel Jacobowitz  <drow@mvista.com>

	* defs.h (ALIGN64): Define for MIPS.
	* io.c (PREAD_OFFSET_ARG): Define.
	(sys_pread, sys_pwrite): Use it.
	* process.c (struct_user_offsets) [SH]: Check whether REG_XDREG0
	is defined.
	* linux/sh/syscallent.h (pread, pwrite): Take six arguments.
	(truncate64, ftruncate64): Pretty-print.
	* linux/mips/syscallent.h (pread, pwrite): Take six arguments.
	(truncate64, ftruncate64): Take four arguments.
diff --git a/defs.h b/defs.h
index ff06f4e..504cbf5 100644
--- a/defs.h
+++ b/defs.h
@@ -562,7 +562,8 @@
 #endif /* SUPPORTED_PERSONALITIES >= 3 */
 
 #if defined(FREEBSD) || (defined(LINUX) \
-			 && defined(POWERPC) && !defined(__powerpc64__))
+			 && defined(POWERPC) && !defined(__powerpc64__)) \
+  || (defined (LINUX) && defined (MIPS) && !defined(__mips64))
 /* ARRGH!  off_t args are aligned on 64 bit boundaries! */
 #define ALIGN64(tcp,arg)						\
 do {									\
diff --git a/io.c b/io.c
index 893ee61..65b48fd 100644
--- a/io.c
+++ b/io.c
@@ -231,6 +231,18 @@
 #endif /* FREEBSD */
 
 #ifdef LINUX
+
+/* The SH4 ABI does allow long longs in odd-numbered registers, but
+   does not allow them to be split between registers and memory - and
+   there are only four argument registers for normal functions.  As a
+   result pread takes an extra padding argument before the offset.  This
+   was changed late in the 2.4 series (around 2.4.20).  */
+#if defined(SH)
+#define PREAD_OFFSET_ARG 4
+#else
+#define PREAD_OFFSET_ARG 3
+#endif
+
 int
 sys_pread(tcp)
 struct tcb *tcp;
@@ -242,9 +254,9 @@
 			tprintf("%#lx", tcp->u_arg[1]);
 		else
 			printstr(tcp, tcp->u_arg[1], tcp->u_rval);
-		ALIGN64 (tcp, 3); /* PowerPC alignment restriction */
+		ALIGN64 (tcp, PREAD_OFFSET_ARG); /* PowerPC alignment restriction */
 		tprintf(", %lu, %llu", tcp->u_arg[2],
-			*(unsigned long long *)&tcp->u_arg[3]);
+			*(unsigned long long *)&tcp->u_arg[PREAD_OFFSET_ARG]);
 	}
 	return 0;
 }
@@ -256,9 +268,9 @@
 	if (entering(tcp)) {
 		tprintf("%ld, ", tcp->u_arg[0]);
 		printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
-		ALIGN64 (tcp, 3); /* PowerPC alignment restriction */
+		ALIGN64 (tcp, PREAD_OFFSET_ARG); /* PowerPC alignment restriction */
 		tprintf(", %lu, %llu", tcp->u_arg[2],
-			*(unsigned long long *)&tcp->u_arg[3]);
+			*(unsigned long long *)&tcp->u_arg[PREAD_OFFSET_ARG]);
 	}
 	return 0;
 }
diff --git a/linux/mips/syscallent.h b/linux/mips/syscallent.h
index be6ed70..8f41314 100644
--- a/linux/mips/syscallent.h
+++ b/linux/mips/syscallent.h
@@ -4198,8 +4198,8 @@
 	{ 4,	TS,	sys_rt_sigtimedwait,	"rt_sigtimedwait"},/* 4197 */
 	{ 3,	TS,	sys_rt_sigqueueinfo,	"rt_sigqueueinfo"},/* 4198 */
 	{ 2,	TS,	sys_rt_sigsuspend,	"rt_siguspend"	}, /* 4199 */
-	{ 5,	TF,	sys_pread,		"pread"		}, /* 4200 */
-	{ 5,	TF,	sys_pwrite,		"pwrite"	}, /* 4201 */
+	{ 6,	TF,	sys_pread,		"pread"		}, /* 4200 */
+	{ 6,	TF,	sys_pwrite,		"pwrite"	}, /* 4201 */
 	{ 3,	TF,	sys_chown,		"chown"		}, /* 4202 */
 	{ 2,	TF,	sys_getcwd,		"getcwd"	}, /* 4203 */
 	{ 2,	0,	sys_capget,		"capget"	}, /* 4204 */
@@ -4209,8 +4209,8 @@
 	{ 0,	0,	printargs,		"SYS_4208"	}, /* 4208 */
 	{ 0,	0,	printargs,		"SYS_4209"	}, /* 4209 */
 	{ 6,	0,	sys_mmap,		"mmap"		}, /* 4210 */
-	{ 2,	TF,	sys_truncate64,		"truncate64"	}, /* 4211 */
-	{ 2,	TF,	sys_ftruncate64,	"ftruncate64"	}, /* 4212 */
+	{ 4,	TF,	sys_truncate64,		"truncate64"	}, /* 4211 */
+	{ 4,	TF,	sys_ftruncate64,	"ftruncate64"	}, /* 4212 */
 	{ 2,	TF,	printargs,		"stat64"	}, /* 4213 */
 	{ 2,	TF,	sys_lstat64,		"lstat64"	}, /* 4214 */
 	{ 2,	TF,	sys_fstat64,		"fstat64"	}, /* 4215 */
diff --git a/linux/sh/syscallent.h b/linux/sh/syscallent.h
index 2b83dda..f6a01a6 100644
--- a/linux/sh/syscallent.h
+++ b/linux/sh/syscallent.h
@@ -211,8 +211,8 @@
 	{ 3,	TS,	sys_rt_sigqueueinfo,    "rt_sigqueueinfo"}, /* 178 */
 	{ 2,	TS,	sys_rt_sigsuspend,	"rt_sigsuspend"	}, /* 179 */
 
-	{ 5,	TF,	sys_pread,		"pread"		}, /* 180 */
-	{ 5,	TF,	sys_pwrite,		"pwrite"	}, /* 181 */
+	{ 6,	TF,	sys_pread,		"pread"		}, /* 180 */
+	{ 6,	TF,	sys_pwrite,		"pwrite"	}, /* 181 */
 	{ 3,	TF,	sys_chown,		"chown"		}, /* 182 */
 	{ 2,	0,	sys_getcwd,		"getcwd"	}, /* 183 */
 	{ 2,	0,	sys_capget,		"capget"	}, /* 184 */
@@ -224,8 +224,8 @@
 	{ 0,	TP,	sys_vfork,		"vfork"		}, /* 190 */
 	{ 5,	0,	printargs,		"getrlimit"	}, /* 191 */
 	{ 6,	0,	sys_mmap,		"mmap2"		}, /* 192 */
-	{ 5,	0,	printargs,		"truncate64"	}, /* 193 */
-	{ 5,	0,	printargs,		"ftruncate64"	}, /* 194 */
+	{ 5,	0,	sys_truncate64,		"truncate64"	}, /* 193 */
+	{ 5,	0,	sys_ftruncate64,	"ftruncate64"	}, /* 194 */
 	{ 2,	TF,	sys_stat64,		"stat64"	}, /* 195 */
 	{ 2,	TF,	sys_lstat64,		"lstat64"	}, /* 196 */
 	{ 2,	TF,	sys_fstat64,		"fstat64"	}, /* 197 */
diff --git a/process.c b/process.c
index 231820f..75a316d 100644
--- a/process.c
+++ b/process.c
@@ -2465,6 +2465,7 @@
        { 4*(REG_FPREG0+13),    "4*REG_FPREG13"                         },
        { 4*(REG_FPREG0+14),    "4*REG_FPREG14"                         },
        { 4*REG_FPREG15,        "4*REG_FPREG15"                         },
+#ifdef REG_XDREG0
        { 4*REG_XDREG0,         "4*REG_XDREG0"                          },
        { 4*(REG_XDREG0+2),     "4*REG_XDREG2"                          },
        { 4*(REG_XDREG0+4),     "4*REG_XDREG4"                          },
@@ -2473,6 +2474,7 @@
        { 4*(REG_XDREG0+10),    "4*REG_XDREG10"                         },
        { 4*(REG_XDREG0+12),    "4*REG_XDREG12"                         },
        { 4*REG_XDREG14,        "4*REG_XDREG14"                         },
+#endif
        { 4*REG_FPSCR,          "4*REG_FPSCR"                           },
 #endif /* SH */
 #ifdef SH64