AVR32 support by Hans-Christian Egtvedt
(hans-christian.egtvedt AT atmel.com).
* configure.ac: Make it recognize avr32.
* defs.h: Define LINUX_AVR32.
* linux/avr32/syscallent.h: New file.
* Makefile.am: Reference linux/avr32/syscallent.h.
* proc.c (change_syscall, setarg): Add support for avr32.
(struct xlat struct_user_offsets[]): Ditto.
* syscall.c (get_scno): Ditto.
(get_error, force_result, syscall_enter): Ditto.
* util.c (getpc, printcall): Ditto.
diff --git a/syscall.c b/syscall.c
index 128622d..10b6627 100644
--- a/syscall.c
+++ b/syscall.c
@@ -323,12 +323,12 @@
 	int i;
 	int rc = -1;
 
-  	if (isdigit((unsigned char)*s)) {
- 		int i = atoi(s);
+	if (isdigit((unsigned char)*s)) {
+		int i = atoi(s);
 		if (i < 0 || i >= MAX_QUALS)
- 			return -1;
- 		qualify_one(i, opt, not, -1);
- 		return 0;
+			return -1;
+		qualify_one(i, opt, not, -1);
+		return 0;
 	}
 	for (i = 0; i < nsyscalls0; i++)
 		if (strcmp(s, sysent0[i].sys_name) == 0) {
@@ -364,12 +364,12 @@
 	int i;
 	char buf[32];
 
-  	if (isdigit((unsigned char)*s)) {
- 		int signo = atoi(s);
- 		if (signo < 0 || signo >= MAX_QUALS)
- 			return -1;
- 		qualify_one(signo, opt, not, -1);
- 		return 0;
+	if (isdigit((unsigned char)*s)) {
+		int signo = atoi(s);
+		if (signo < 0 || signo >= MAX_QUALS)
+			return -1;
+		qualify_one(signo, opt, not, -1);
+		return 0;
 	}
 	if (strlen(s) >= sizeof buf)
 		return -1;
@@ -753,6 +753,8 @@
 #elif defined (ALPHA)
 	static long r0;
 	static long a3;
+#elif defined(AVR32)
+	static struct pt_regs regs;
 #elif defined (SPARC) || defined (SPARC64)
 	static struct regs regs;
 	static unsigned long trap;
@@ -814,11 +816,11 @@
 
 	if (syscall_mode != -ENOSYS) {
 		/*
- 		 * Since kernel version 2.5.44 the scno gets passed in gpr2.
+		 * Since kernel version 2.5.44 the scno gets passed in gpr2.
 		 */
 		scno = syscall_mode;
 	} else {
-	       	/*
+		/*
 		 * Old style of "passing" the scno via the SVC instruction.
 		 */
 
@@ -899,6 +901,25 @@
 			return 0;
 		}
 	}
+# elif defined(AVR32)
+	/*
+	 * Read complete register set in one go.
+	 */
+	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
+		return -1;
+
+	/*
+	 * We only need to grab the syscall number on syscall entry.
+	 */
+	if (!(tcp->flags & TCB_INSYSCALL)) {
+		scno = regs.r8;
+
+		/* Check if we return from execve. */
+		if (tcp->flags & TCB_WAITEXECVE) {
+			tcp->flags &= ~TCB_WAITEXECVE;
+			return 0;
+		}
+	}
 # elif defined(BFIN)
 	if (upeek(tcp, PT_ORIG_P0, &scno))
 		return -1;
@@ -913,7 +934,7 @@
 		return -1;
 
 	if (!(tcp->flags & TCB_INSYSCALL)) {
-	  	static int currpers = -1;
+		static int currpers = -1;
 		long val;
 		int pid = tcp->pid;
 
@@ -1129,10 +1150,10 @@
 	}
 # elif defined (MIPS)
 	if (upeek(tcp, REG_A3, &a3) < 0)
-	  	return -1;
+		return -1;
 	if(!(tcp->flags & TCB_INSYSCALL)) {
-	  	if (upeek(tcp, REG_V0, &scno) < 0)
-		  	return -1;
+		if (upeek(tcp, REG_V0, &scno) < 0)
+			return -1;
 
 		/* Check if we return from execve. */
 		if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
@@ -1148,8 +1169,8 @@
 			}
 		}
 	} else {
-	  	if (upeek(tcp, REG_V0, &r2) < 0)
-	    		return -1;
+		if (upeek(tcp, REG_V0, &r2) < 0)
+			return -1;
 	}
 # elif defined (ALPHA)
 	if (upeek(tcp, REG_A3, &a3) < 0)
@@ -1270,7 +1291,7 @@
 		   our purposes, make strace print what it *should* have been */
 		long correct_scno = (scno & 0xff);
 		if (debug)
-	    		fprintf(stderr,
+			fprintf(stderr,
 				"Detected glibc bug: bogus system call"
 				" number = %ld, correcting to %ld\n",
 				scno,
@@ -1590,10 +1611,10 @@
 	}
 # elif defined(MIPS)
 		if (a3) {
-		  	tcp->u_rval = -1;
+			tcp->u_rval = -1;
 			u_error = r2;
 		} else {
-		  	tcp->u_rval = r2;
+			tcp->u_rval = r2;
 			u_error = 0;
 		}
 # elif defined(POWERPC)
@@ -1623,6 +1644,15 @@
 			tcp->u_rval = regs.ARM_r0;
 			u_error = 0;
 		}
+# elif defined(AVR32)
+		if (regs.r12 && (unsigned) -regs.r12 < nerrnos) {
+			tcp->u_rval = -1;
+			u_error = -regs.r12;
+		}
+		else {
+			tcp->u_rval = regs.r12;
+			u_error = 0;
+		}
 # elif defined(BFIN)
 		if (is_negated_errno(r0)) {
 			tcp->u_rval = -1;
@@ -1760,10 +1790,10 @@
 #endif /* SVR4 */
 #ifdef FREEBSD
 		if (regs.r_eflags & PSL_C) {
- 		        tcp->u_rval = -1;
+			tcp->u_rval = -1;
 		        u_error = regs.r_eax;
 		} else {
-		        tcp->u_rval = regs.r_eax;
+			tcp->u_rval = regs.r_eax;
 			tcp->u_lrval =
 			  ((unsigned long long) regs.r_edx << 32) +  regs.r_eax;
 		        u_error = 0;
@@ -1827,7 +1857,7 @@
 	/* PTRACE_POKEUSER is OK even for n32 since rval is only a long.  */
 	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
 	    ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), r2) < 0)
-	    	return -1;
+		return -1;
 # elif defined(POWERPC)
 	if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
 		return -1;
@@ -1850,6 +1880,10 @@
 	regs.ARM_r0 = error ? -error : rval;
 	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*0), regs.ARM_r0) < 0)
 		return -1;
+# elif defined(AVR32)
+	regs.r12 = error ? -error : rval;
+	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_R12, regs.r12) < 0)
+		return -1;
 # elif defined(ALPHA)
 	if (error) {
 		a3 = -1;
@@ -1951,7 +1985,7 @@
 		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
 			tcp->u_nargs = sysent[tcp->scno].nargs;
 		else
-     	        	tcp->u_nargs = MAX_ARGS;
+			tcp->u_nargs = MAX_ARGS;
 		for (i = 0; i < tcp->u_nargs; i++) {
 			if (upeek(tcp,i==0 ? PT_ORIGGPR2:PT_GPR2+i*sizeof(long), &tcp->u_arg[i]) < 0)
 				return -1;
@@ -1963,7 +1997,7 @@
 		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
 			tcp->u_nargs = sysent[tcp->scno].nargs;
 		else
-     	        	tcp->u_nargs = MAX_ARGS;
+			tcp->u_nargs = MAX_ARGS;
 		for (i = 0; i < tcp->u_nargs; i++) {
 			/* WTA: if scno is out-of-bounds this will bomb. Add range-check
 			 * for scno somewhere above here!
@@ -2033,12 +2067,12 @@
 	/* N32 and N64 both use up to six registers.  */
 	{
 		unsigned long long regs[38];
-	  	int i, nargs;
+		int i, nargs;
 
 		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
 			nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
 		else
-     	        	nargs = tcp->u_nargs = MAX_ARGS;
+			nargs = tcp->u_nargs = MAX_ARGS;
 
 		if (do_ptrace(PTRACE_GETREGS, tcp, NULL, (long) &regs) < 0)
 			return -1;
@@ -2052,26 +2086,26 @@
 	}
 #elif defined (MIPS)
 	{
-	  	long sp;
-	  	int i, nargs;
+		long sp;
+		int i, nargs;
 
 		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
 			nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
 		else
-     	        	nargs = tcp->u_nargs = MAX_ARGS;
+			nargs = tcp->u_nargs = MAX_ARGS;
 		if (nargs > 4) {
-		  	if (upeek(tcp, REG_SP, &sp) < 0)
-			  	return -1;
+			if (upeek(tcp, REG_SP, &sp) < 0)
+				return -1;
 			for (i = 0; i < 4; i++) {
-			  	if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i])<0)
-				  	return -1;
+				if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i])<0)
+					return -1;
 			}
 			umoven(tcp, sp+16, (nargs-4) * sizeof(tcp->u_arg[0]),
 			       (char *)(tcp->u_arg + 4));
 		} else {
-		  	for (i = 0; i < nargs; i++) {
-			  	if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
-				  	return -1;
+			for (i = 0; i < nargs; i++) {
+				if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
+					return -1;
 			}
 		}
 	}
@@ -2084,7 +2118,7 @@
 		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
 			tcp->u_nargs = sysent[tcp->scno].nargs;
 		else
-     	        	tcp->u_nargs = MAX_ARGS;
+			tcp->u_nargs = MAX_ARGS;
 		for (i = 0; i < tcp->u_nargs; i++) {
 			if (upeek(tcp, (i==0) ?
 				(sizeof(unsigned long)*PT_ORIG_R3) :
@@ -2100,7 +2134,7 @@
 		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
 			tcp->u_nargs = sysent[tcp->scno].nargs;
 		else
-     	        	tcp->u_nargs = MAX_ARGS;
+			tcp->u_nargs = MAX_ARGS;
 		for (i = 0; i < tcp->u_nargs; i++)
 			tcp->u_arg[i] = *((&regs.r_o0) + i);
 	}
@@ -2111,7 +2145,7 @@
 		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
 			tcp->u_nargs = sysent[tcp->scno].nargs;
 		else
-     	        	tcp->u_nargs = MAX_ARGS;
+			tcp->u_nargs = MAX_ARGS;
 		for (i = 0; i < tcp->u_nargs; i++) {
 			if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
 				return -1;
@@ -2127,7 +2161,15 @@
 			tcp->u_nargs = MAX_ARGS;
 		for (i = 0; i < tcp->u_nargs; i++)
 			tcp->u_arg[i] = regs.uregs[i];
- 	}
+	}
+#elif defined(AVR32)
+	tcp->u_nargs = sysent[tcp->scno].nargs;
+	tcp->u_arg[0] = regs.r12;
+	tcp->u_arg[1] = regs.r11;
+	tcp->u_arg[2] = regs.r10;
+	tcp->u_arg[3] = regs.r9;
+	tcp->u_arg[4] = regs.r5;
+	tcp->u_arg[5] = regs.r3;
 #elif defined(BFIN)
 	{
 		int i;
@@ -2189,7 +2231,7 @@
 		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
 			tcp->u_nargs = sysent[tcp->scno].nargs;
 		else
-     	        	tcp->u_nargs = MAX_ARGS;
+			tcp->u_nargs = MAX_ARGS;
 		for (i = 0; i < tcp->u_nargs; i++) {
 			if (upeek(tcp, argreg[current_personality][i]*8, &tcp->u_arg[i]) < 0)
 				return -1;
@@ -2218,7 +2260,7 @@
 		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
 			tcp->u_nargs = sysent[tcp->scno].nargs;
 		else
-     	        	tcp->u_nargs = MAX_ARGS;
+			tcp->u_nargs = MAX_ARGS;
 		for (i = 0; i < tcp->u_nargs; i++) {
 			if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
 				return -1;
@@ -2232,7 +2274,7 @@
 		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
 			tcp->u_nargs = sysent[tcp->scno].nargs;
 		else
-     	        	tcp->u_nargs = MAX_ARGS;
+			tcp->u_nargs = MAX_ARGS;
 		for (i = 0; i < tcp->u_nargs; i++) {
 			struct user *u;
 
@@ -2298,7 +2340,7 @@
 	    sysent[tcp->scno].nargs > tcp->status.val)
 		tcp->u_nargs = sysent[tcp->scno].nargs;
 	else
-	  	tcp->u_nargs = tcp->status.val;
+		tcp->u_nargs = tcp->status.val;
 	if (tcp->u_nargs < 0)
 		tcp->u_nargs = 0;
 	if (tcp->u_nargs > MAX_ARGS)