2006-01-12  Roland McGrath  <roland@redhat.com>

	* defs.h [LINUXSPARC] (PERSONALITY0_WORDSIZE, PERSONALITY1_WORDSIZE):
	New macros.
	[SPARC64] (PERSONALITY2_WORDSIZE): New macro.
	[X86_64] (PERSONALITY0_WORDSIZE, PERSONALITY1_WORDSIZE): New macros.
	* syscall.c (PERSONALITY0_WORDSIZE): New macro if undefined.
	(personality_wordsize): New variable.
	(decode_subcall): Use it for size of argument words.
	Fixes RH#174354.
diff --git a/defs.h b/defs.h
index a04b78f..1e715cf 100644
--- a/defs.h
+++ b/defs.h
@@ -194,9 +194,12 @@
 #ifdef LINUXSPARC
 #include <linux/a.out.h>
 #include <asm/psr.h>
+#define PERSONALITY0_WORDSIZE 4
+#define PERSONALITY1_WORDSIZE 4
 #undef  SUPPORTED_PERSONALITIES
 #if defined(SPARC64)
 #define SUPPORTED_PERSONALITIES 3
+#define PERSONALITY2_WORDSIZE 8
 #else
 #define SUPPORTED_PERSONALITIES 2
 #endif /* SPARC64 */
@@ -205,6 +208,8 @@
 #ifdef X86_64
 #undef SUPPORTED_PERSONALITIES
 #define SUPPORTED_PERSONALITIES 2
+#define PERSONALITY0_WORDSIZE 8
+#define PERSONALITY1_WORDSIZE 4
 #endif
 
 #ifdef SVR4
diff --git a/syscall.c b/syscall.c
index f5ce8d1..22893a7 100644
--- a/syscall.c
+++ b/syscall.c
@@ -183,6 +183,19 @@
 
 int current_personality;
 
+#ifndef PERSONALITY0_WORDSIZE
+# define PERSONALITY0_WORDSIZE sizeof(long)
+#endif
+const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
+	PERSONALITY0_WORDSIZE,
+#if SUPPORTED_PERSONALITIES > 1
+	PERSONALITY1_WORDSIZE,
+#endif
+#if SUPPORTED_PERSONALITIES > 2
+	PERSONALITY2_WORDSIZE,
+#endif
+};;
+
 int
 set_personality(personality)
 int personality;
@@ -628,8 +641,9 @@
 int nsubcalls;
 enum subcall_style style;
 {
-	long addr, mask, arg;
+	unsigned long addr, mask;
 	int i;
+	int size = personality_wordsize[current_personality];
 
 	switch (style) {
 	case shift_style:
@@ -649,10 +663,21 @@
 		tcp->scno = subcall + tcp->u_arg[0];
 		addr = tcp->u_arg[1];
 		for (i = 0; i < sysent[tcp->scno].nargs; i++) {
-			if (umove(tcp, addr, &arg) < 0)
-				arg = 0;
-			tcp->u_arg[i] = arg;
-			addr += sizeof(arg);
+			if (size == sizeof(int)) {
+				unsigned int arg;
+				if (umove(tcp, addr, &arg) < 0)
+					arg = 0;
+				tcp->u_arg[i] = arg;
+			}
+			else if (size == sizeof(long)) {
+				unsigned long arg;
+				if (umove(tcp, addr, &arg) < 0)
+					arg = 0;
+				tcp->u_arg[i] = arg;
+			}
+			else
+				abort();
+			addr += size;
 		}
 		tcp->u_nargs = sysent[tcp->scno].nargs;
 		break;