mn10300: add the MN10300/AM33 architecture to the kernel

Add architecture support for the MN10300/AM33 CPUs produced by MEI to the
kernel.

This patch also adds board support for the ASB2303 with the ASB2308 daughter
board, and the ASB2305.  The only processor supported is the MN103E010, which
is an AM33v2 core plus on-chip devices.

[akpm@linux-foundation.org: nuke cvs control strings]
Signed-off-by: Masakazu Urade <urade.masakazu@jp.panasonic.com>
Signed-off-by: Koichi Yasutake <yasutake.koichi@jp.panasonic.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
diff --git a/arch/mn10300/lib/Makefile b/arch/mn10300/lib/Makefile
new file mode 100644
index 0000000..fdfa9ec
--- /dev/null
+++ b/arch/mn10300/lib/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the MN10300-specific library files..
+#
+
+lib-y = delay.o usercopy.o checksum.o bitops.o memcpy.o memmove.o memset.o
+lib-y += do_csum.o
+lib-y += __ashldi3.o __ashrdi3.o __lshrdi3.o negdi2.o
diff --git a/arch/mn10300/lib/__ashldi3.S b/arch/mn10300/lib/__ashldi3.S
new file mode 100644
index 0000000..a51a9506
--- /dev/null
+++ b/arch/mn10300/lib/__ashldi3.S
@@ -0,0 +1,51 @@
+/* MN10300 64-bit arithmetic left shift
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/cache.h>
+
+        .text
+        .balign	L1_CACHE_BYTES
+
+###############################################################################
+#
+# unsigned long long __ashldi3(unsigned long long value [D1:D0],
+#			       unsigned by [(12,SP)])
+#
+###############################################################################
+        .globl	__ashldi3
+        .type	__ashldi3,@function
+__ashldi3:
+	mov	(12,sp),a0
+	and	+63,a0
+	beq	__ashldi3_zero
+
+	cmp	+31,a0
+	bhi	__ashldi3_32plus
+
+	# the count is in the range 1-31
+	asl	a0,d1
+
+	mov	+32,a1
+	sub	a0,a1,a1			# a1 = 32 - count
+	lsr	a1,d0,a1			# get overflow from LSW -> MSW
+
+	or_asl	a1,d1,a0,d0			# insert overflow into MSW and
+						# shift the LSW
+	rets
+
+	.balign	L1_CACHE_BYTES
+	# the count is in the range 32-63
+__ashldi3_32plus:
+	asl	a0,d0,d1
+	clr	d0
+__ashldi3_zero:
+	rets
+
+	.size	__ashldi3, .-__ashldi3
diff --git a/arch/mn10300/lib/__ashrdi3.S b/arch/mn10300/lib/__ashrdi3.S
new file mode 100644
index 0000000..6f42382
--- /dev/null
+++ b/arch/mn10300/lib/__ashrdi3.S
@@ -0,0 +1,52 @@
+/* MN10300 64-bit arithmetic right shift
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/cache.h>
+
+        .text
+        .balign	L1_CACHE_BYTES
+
+###############################################################################
+#
+# unsigned long long __ashrdi3(unsigned long long value [D1:D0],
+#			       unsigned by [(12,SP)])
+#
+###############################################################################
+        .globl	__ashrdi3
+        .type	__ashrdi3,@function
+__ashrdi3:
+	mov	(12,sp),a0
+	and	+63,a0
+	beq	__ashrdi3_zero
+
+	cmp	+31,a0
+	bhi	__ashrdi3_32plus
+
+	# the count is in the range 1-31
+	lsr	a0,d0
+
+	mov	+32,a1
+	sub	a0,a1,a1			# a1 = 32 - count
+	asl	a1,d1,a1			# get underflow from MSW -> LSW
+
+	or_asr	a1,d0,a0,d1			# insert underflow into LSW and
+						# shift the MSW
+	rets
+
+	.balign	L1_CACHE_BYTES
+	# the count is in the range 32-63
+__ashrdi3_32plus:
+	asr	a0,d1,d0
+	ext	d0				# sign-extend result through MDR
+	mov	mdr,d1
+__ashrdi3_zero:
+	rets
+
+	.size	__ashrdi3, .-__ashrdi3
diff --git a/arch/mn10300/lib/__lshrdi3.S b/arch/mn10300/lib/__lshrdi3.S
new file mode 100644
index 0000000..a686aef
--- /dev/null
+++ b/arch/mn10300/lib/__lshrdi3.S
@@ -0,0 +1,52 @@
+/* MN10300 64-bit logical right shift
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <asm/cache.h>
+
+        .text
+        .balign	L1_CACHE_BYTES
+
+###############################################################################
+#
+# unsigned long long __lshrdi3(unsigned long long value [D1:D0],
+#			       unsigned by [(12,SP)])
+#
+###############################################################################
+        .globl	__lshrdi3
+        .type	__lshrdi3,@function
+__lshrdi3:
+	mov	(12,sp),a0
+	and	+63,a0
+	beq	__lshrdi3_zero
+
+	cmp	+31,a0
+	bhi	__lshrdi3_32plus
+
+	# the count is in the range 1-31
+	lsr	a0,d0
+
+	mov	+32,a1
+	sub	a0,a1,a1			# a1 = 32 - count
+	asl	a1,d1,a1			# get underflow from MSW -> LSW
+
+	or_lsr	a1,d0,a0,d1			# insert underflow into LSW and
+						# shift the MSW
+	rets
+
+	.balign	L1_CACHE_BYTES
+	# the count is in the range 32-63
+__lshrdi3_32plus:
+	lsr	a0,d1,d0
+	clr	d1
+__lshrdi3_zero:
+	rets
+
+	.size	__lshrdi3, .-__lshrdi3
diff --git a/arch/mn10300/lib/ashrdi3.c b/arch/mn10300/lib/ashrdi3.c
new file mode 100644
index 0000000..c54f61d
--- /dev/null
+++ b/arch/mn10300/lib/ashrdi3.c
@@ -0,0 +1,61 @@
+/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public Licence as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public Licence for more details.
+
+You should have received a copy of the GNU General Public Licence
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#define BITS_PER_UNIT 8
+
+typedef 	 int SItype	__attribute__((mode(SI)));
+typedef unsigned int USItype	__attribute__((mode(SI)));
+typedef		 int DItype	__attribute__((mode(DI)));
+typedef		 int word_type	__attribute__((mode(__word__)));
+
+struct DIstruct {
+	SItype low;
+	SItype high;
+};
+
+union DIunion {
+	struct DIstruct	s;
+	DItype		ll;
+};
+
+DItype __ashrdi3(DItype u, word_type b)
+{
+	union DIunion w;
+	union DIunion uu;
+	word_type bm;
+
+	if (b == 0)
+		return u;
+
+	uu.ll = u;
+
+	bm = (sizeof(SItype) * BITS_PER_UNIT) - b;
+	if (bm <= 0) {
+		/* w.s.high = 1..1 or 0..0 */
+		w.s.high = uu.s.high >> (sizeof(SItype) * BITS_PER_UNIT - 1);
+		w.s.low = uu.s.high >> -bm;
+	} else {
+		USItype carries = (USItype)uu.s.high << bm;
+		w.s.high = uu.s.high >> b;
+		w.s.low = ((USItype)uu.s.low >> b) | carries;
+	}
+
+	return w.ll;
+}
diff --git a/arch/mn10300/lib/bitops.c b/arch/mn10300/lib/bitops.c
new file mode 100644
index 0000000..440a7dc
--- /dev/null
+++ b/arch/mn10300/lib/bitops.c
@@ -0,0 +1,51 @@
+/* MN10300 Non-trivial bit operations
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <asm/bitops.h>
+#include <asm/system.h>
+
+/*
+ * try flipping a bit using BSET and BCLR
+ */
+void change_bit(int nr, volatile void *addr)
+{
+	if (test_bit(nr, addr))
+		goto try_clear_bit;
+
+try_set_bit:
+	if (!test_and_set_bit(nr, addr))
+		return;
+
+try_clear_bit:
+	if (test_and_clear_bit(nr, addr))
+		return;
+
+	goto try_set_bit;
+}
+
+/*
+ * try flipping a bit using BSET and BCLR and returning the old value
+ */
+int test_and_change_bit(int nr, volatile void *addr)
+{
+	if (test_bit(nr, addr))
+		goto try_clear_bit;
+
+try_set_bit:
+	if (!test_and_set_bit(nr, addr))
+		return 0;
+
+try_clear_bit:
+	if (test_and_clear_bit(nr, addr))
+		return 1;
+
+	goto try_set_bit;
+}
diff --git a/arch/mn10300/lib/checksum.c b/arch/mn10300/lib/checksum.c
new file mode 100644
index 0000000..274f29e
--- /dev/null
+++ b/arch/mn10300/lib/checksum.c
@@ -0,0 +1,99 @@
+/* MN10300 Optimised checksumming wrappers
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+#include <asm/checksum.h>
+#include "internal.h"
+
+static inline unsigned short from32to16(__wsum sum)
+{
+	asm("	add	%1,%0		\n"
+	    "	addc	0xffff,%0	\n"
+	    : "=r" (sum)
+	    : "r" (sum << 16), "0" (sum & 0xffff0000)
+	    );
+	return sum >> 16;
+}
+
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+	return ~do_csum(iph, ihl * 4);
+}
+EXPORT_SYMBOL(ip_fast_csum);
+
+__wsum csum_partial(const void *buff, int len, __wsum sum)
+{
+	__wsum result;
+
+	result = do_csum(buff, len);
+	result += sum;
+	if (sum > result)
+		result++;
+	return result;
+}
+EXPORT_SYMBOL(csum_partial);
+
+__sum16 ip_compute_csum(const void *buff, int len)
+{
+	return ~from32to16(do_csum(buff, len));
+}
+EXPORT_SYMBOL(ip_compute_csum);
+
+__wsum csum_partial_copy(const void *src, void *dst, int len, __wsum sum)
+{
+	copy_from_user(dst, src, len);
+	return csum_partial(dst, len, sum);
+}
+EXPORT_SYMBOL(csum_partial_copy);
+
+__wsum csum_partial_copy_nocheck(const void *src, void *dst,
+				 int len, __wsum sum)
+{
+	sum = csum_partial(src, len, sum);
+	memcpy(dst, src, len);
+	return sum;
+}
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
+
+__wsum csum_partial_copy_from_user(const void *src, void *dst,
+				   int len, __wsum sum,
+				   int *err_ptr)
+{
+	int missing;
+
+	missing = copy_from_user(dst, src, len);
+	if (missing) {
+		memset(dst + len - missing, 0, missing);
+		*err_ptr = -EFAULT;
+	}
+
+	return csum_partial(dst, len, sum);
+}
+EXPORT_SYMBOL(csum_partial_copy_from_user);
+
+__wsum csum_and_copy_to_user(const void *src, void *dst,
+			     int len, __wsum sum,
+			     int *err_ptr)
+{
+	int missing;
+
+	missing = copy_to_user(dst, src, len);
+	if (missing) {
+		memset(dst + len - missing, 0, missing);
+		*err_ptr = -EFAULT;
+	}
+
+	return csum_partial(src, len, sum);
+}
+EXPORT_SYMBOL(csum_and_copy_to_user);
diff --git a/arch/mn10300/lib/delay.c b/arch/mn10300/lib/delay.c
new file mode 100644
index 0000000..cce66bc
--- /dev/null
+++ b/arch/mn10300/lib/delay.c
@@ -0,0 +1,50 @@
+/* MN10300 Short delay interpolation routines
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <asm/div64.h>
+
+/*
+ * basic delay loop
+ */
+void __delay(unsigned long loops)
+{
+	int d0;
+
+	asm volatile(
+		"	bra	1f	\n"
+		"	.align	4	\n"
+		"1:	bra	2f	\n"
+		"	.align	4	\n"
+		"2:	add	-1,%0	\n"
+		"	bne	2b	\n"
+		: "=&d" (d0)
+		: "0" (loops));
+}
+EXPORT_SYMBOL(__delay);
+
+/*
+ * handle a delay specified in terms of microseconds
+ */
+void __udelay(unsigned long usecs)
+{
+	signed long ioclk, stop;
+
+	/* usecs * CLK / 1E6 */
+	stop = __muldiv64u(usecs, MN10300_TSCCLK, 1000000);
+	stop = TMTSCBC - stop;
+
+	do {
+		ioclk = TMTSCBC;
+	} while (stop < ioclk);
+}
+EXPORT_SYMBOL(__udelay);
diff --git a/arch/mn10300/lib/do_csum.S b/arch/mn10300/lib/do_csum.S
new file mode 100644
index 0000000..e138994
--- /dev/null
+++ b/arch/mn10300/lib/do_csum.S
@@ -0,0 +1,162 @@
+/* Optimised simple memory checksum
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/cache.h>
+
+        .section .text
+        .balign	L1_CACHE_BYTES
+
+###############################################################################
+#
+# unsigned int do_csum(const unsigned char *buff, size_t len)
+#
+###############################################################################
+	.globl	do_csum
+        .type	do_csum,@function
+do_csum:
+	movm	[d2,d3],(sp)
+	mov	d0,(12,sp)
+	mov	d1,(16,sp)
+	mov	d1,d2				# count
+	mov	d0,a0				# buff
+	clr	d1				# accumulator
+
+	cmp	+0,d2
+	beq	do_csum_done			# return if zero-length buffer
+
+	# 4-byte align the buffer pointer
+	btst	+3,a0
+	beq	do_csum_now_4b_aligned
+
+	btst	+1,a0
+	beq	do_csum_addr_not_odd
+	movbu	(a0),d0
+	inc	a0
+	asl	+8,d0
+	add	d0,d1
+	addc	+0,d1
+	add	-1,d2
+do_csum_addr_not_odd:
+
+	cmp	+2,d2
+	bcs	do_csum_fewer_than_4
+	btst	+2,a0
+	beq	do_csum_now_4b_aligned
+	movhu	(a0+),d0
+	add	d0,d1
+	addc	+0,d1
+	add	-2,d2
+	cmp	+4,d2
+	bcs	do_csum_fewer_than_4
+
+do_csum_now_4b_aligned:
+	# we want to checksum as much as we can in chunks of 32 bytes
+	cmp	+31,d2
+	bls	do_csum_remainder		# 4-byte aligned remainder
+
+	add	-32,d2
+	mov	+32,d3
+
+do_csum_loop:
+	mov	(a0+),d0
+	add	d0,d1
+	mov	(a0+),e0
+	addc	e0,d1
+	mov	(a0+),e1
+	addc	e1,d1
+	mov	(a0+),e3
+	addc	e3,d1
+	mov	(a0+),d0
+	addc	d0,d1
+	mov	(a0+),e0
+	addc	e0,d1
+	mov	(a0+),e1
+	addc	e1,d1
+	mov	(a0+),e3
+	addc	e3,d1
+	addc	+0,d1
+
+	sub	d3,d2
+	bcc	do_csum_loop
+
+	add	d3,d2
+	beq	do_csum_done
+
+do_csum_remainder:
+	# cut 16-31 bytes down to 0-15
+	cmp	+16,d2
+	bcs	do_csum_fewer_than_16
+	mov	(a0+),d0
+	add	d0,d1
+	mov	(a0+),e0
+	addc	e0,d1
+	mov	(a0+),e1
+	addc	e1,d1
+	mov	(a0+),e3
+	addc	e3,d1
+	addc	+0,d1
+	add	-16,d2
+	beq	do_csum_done
+
+do_csum_fewer_than_16:
+	# copy the remaining whole words
+	cmp	+4,d2
+	bcs	do_csum_fewer_than_4
+	cmp	+8,d2
+	bcs	do_csum_one_word
+	cmp	+12,d2
+	bcs	do_csum_two_words
+	mov	(a0+),d0
+	add	d0,d1
+	addc	+0,d1
+do_csum_two_words:
+	mov	(a0+),d0
+	add	d0,d1
+	addc	+0,d1
+do_csum_one_word:
+	mov	(a0+),d0
+	add	d0,d1
+	addc	+0,d1
+
+do_csum_fewer_than_4:
+	and	+3,d2
+	beq	do_csum_done
+	xor_cmp	d0,d0,+2,d2
+	bcs	do_csum_fewer_than_2
+	movhu	(a0+),d0
+do_csum_fewer_than_2:
+	and	+1,d2
+	beq	do_csum_add_last_bit
+	movbu	(a0),d3
+	add	d3,d0
+do_csum_add_last_bit:
+	add	d0,d1
+	addc	+0,d1
+
+do_csum_done:
+	# compress the checksum down to 16 bits
+	mov	+0xffff0000,d2
+	and	d1,d2
+	asl	+16,d1
+	add	d2,d1,d0
+	addc	+0xffff,d0
+	lsr	+16,d0
+
+	# flip the halves of the word result if the buffer was oddly aligned
+	mov	(12,sp),d1
+	and	+1,d1
+	beq	do_csum_not_oddly_aligned
+	swaph	d0,d0				# exchange bits 15:8 with 7:0
+
+do_csum_not_oddly_aligned:
+	ret	[d2,d3],8
+
+do_csum_end:
+	.size	do_csum, do_csum_end-do_csum
diff --git a/arch/mn10300/lib/internal.h b/arch/mn10300/lib/internal.h
new file mode 100644
index 0000000..0014eee
--- /dev/null
+++ b/arch/mn10300/lib/internal.h
@@ -0,0 +1,15 @@
+/* Internal definitions for the arch part of the kernel library
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+/*
+ * do_csum.S
+ */
+extern unsigned int do_csum(const unsigned char *, size_t);
diff --git a/arch/mn10300/lib/lshrdi3.c b/arch/mn10300/lib/lshrdi3.c
new file mode 100644
index 0000000..e05e64e
--- /dev/null
+++ b/arch/mn10300/lib/lshrdi3.c
@@ -0,0 +1,60 @@
+/* lshrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public Licence as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public Licence for more details.
+
+You should have received a copy of the GNU General Public Licence
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#define BITS_PER_UNIT 8
+
+typedef 	 int SItype	__attribute__((mode(SI)));
+typedef unsigned int USItype	__attribute__((mode(SI)));
+typedef		 int DItype	__attribute__((mode(DI)));
+typedef		 int word_type	__attribute__((mode(__word__)));
+
+struct DIstruct {
+	SItype	low;
+	SItype	high;
+};
+
+union DIunion {
+	struct DIstruct	s;
+	DItype		ll;
+};
+
+DItype __lshrdi3(DItype u, word_type b)
+{
+	union DIunion w;
+	word_type bm;
+	union DIunion uu;
+
+	if (b == 0)
+		return u;
+
+	uu.ll = u;
+
+	bm = (sizeof(SItype) * BITS_PER_UNIT) - b;
+	if (bm <= 0) {
+		w.s.high = 0;
+		w.s.low = (USItype) uu.s.high >> -bm;
+	} else {
+		USItype carries = (USItype) uu.s.high << bm;
+		w.s.high = (USItype) uu.s.high >> b;
+		w.s.low = ((USItype) uu.s.low >> b) | carries;
+	}
+
+	return w.ll;
+}
diff --git a/arch/mn10300/lib/memcpy.S b/arch/mn10300/lib/memcpy.S
new file mode 100644
index 0000000..25fb9bb
--- /dev/null
+++ b/arch/mn10300/lib/memcpy.S
@@ -0,0 +1,135 @@
+/* MN10300 Optimised simple memory to memory copy
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/cache.h>
+
+        .section .text
+        .balign	L1_CACHE_BYTES
+
+###############################################################################
+#
+# void *memcpy(void *dst, const void *src, size_t n)
+#
+###############################################################################
+	.globl	memcpy
+        .type	memcpy,@function
+memcpy:
+	movm	[d2,d3],(sp)
+	mov	d0,(12,sp)
+	mov	d1,(16,sp)
+	mov	(20,sp),d2			# count
+	mov	d0,a0				# dst
+	mov	d1,a1				# src
+	mov	d0,e3				# the return value
+
+	cmp	+0,d2
+	beq	memcpy_done			# return if zero-length copy
+
+	# see if the three parameters are all four-byte aligned
+	or	d0,d1,d3
+	or	d2,d3
+	and	+3,d3
+	bne	memcpy_1			# jump if not
+
+	# we want to transfer as much as we can in chunks of 32 bytes
+	cmp	+31,d2
+	bls	memcpy_4_remainder		# 4-byte aligned remainder
+
+	movm	[exreg1],(sp)
+	add	-32,d2
+	mov	+32,d3
+
+memcpy_4_loop:
+	mov	(a1+),d0
+	mov	(a1+),d1
+	mov	(a1+),e0
+	mov	(a1+),e1
+	mov	(a1+),e4
+	mov	(a1+),e5
+	mov	(a1+),e6
+	mov	(a1+),e7
+	mov	d0,(a0+)
+	mov	d1,(a0+)
+	mov	e0,(a0+)
+	mov	e1,(a0+)
+	mov	e4,(a0+)
+	mov	e5,(a0+)
+	mov	e6,(a0+)
+	mov	e7,(a0+)
+
+	sub	d3,d2
+	bcc	memcpy_4_loop
+
+	movm	(sp),[exreg1]
+	add	d3,d2
+	beq	memcpy_4_no_remainder
+
+memcpy_4_remainder:
+	# cut 4-7 words down to 0-3
+	cmp	+16,d2
+	bcs	memcpy_4_three_or_fewer_words
+	mov	(a1+),d0
+	mov	(a1+),d1
+	mov	(a1+),e0
+	mov	(a1+),e1
+	mov	d0,(a0+)
+	mov	d1,(a0+)
+	mov	e0,(a0+)
+	mov	e1,(a0+)
+	add	-16,d2
+	beq	memcpy_4_no_remainder
+
+	# copy the remaining 1, 2 or 3 words
+memcpy_4_three_or_fewer_words:
+	cmp	+8,d2
+	bcs	memcpy_4_one_word
+	beq	memcpy_4_two_words
+	mov	(a1+),d0
+	mov	d0,(a0+)
+memcpy_4_two_words:
+	mov	(a1+),d0
+	mov	d0,(a0+)
+memcpy_4_one_word:
+	mov	(a1+),d0
+	mov	d0,(a0+)
+
+memcpy_4_no_remainder:
+	# check we copied the correct amount
+	# TODO: REMOVE CHECK
+	sub	e3,a0,d2
+	mov	(20,sp),d1
+	cmp	d2,d1
+	beq	memcpy_done
+	break
+	break
+	break
+
+memcpy_done:
+	mov	e3,a0
+	ret	[d2,d3],8
+
+	# handle misaligned copying
+memcpy_1:
+	add	-1,d2
+	mov	+1,d3
+	setlb					# setlb requires the next insns
+						# to occupy exactly 4 bytes
+
+	sub	d3,d2
+	movbu	(a1),d0
+	movbu	d0,(a0)
+	add_add	d3,a1,d3,a0
+	lcc
+
+	mov	e3,a0
+	ret	[d2,d3],8
+
+memcpy_end:
+	.size	memcpy, memcpy_end-memcpy
diff --git a/arch/mn10300/lib/memmove.S b/arch/mn10300/lib/memmove.S
new file mode 100644
index 0000000..20b07b6
--- /dev/null
+++ b/arch/mn10300/lib/memmove.S
@@ -0,0 +1,160 @@
+/* MN10300 Optimised simple memory to memory copy, with support for overlapping
+ * regions
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/cache.h>
+
+        .section .text
+        .balign	L1_CACHE_BYTES
+
+###############################################################################
+#
+# void *memmove(void *dst, const void *src, size_t n)
+#
+###############################################################################
+	.globl	memmove
+        .type	memmove,@function
+memmove:
+	# fall back to memcpy if dst < src to work bottom up
+	cmp	d1,d0
+	bcs	memmove_memcpy
+
+	# work top down
+	movm	[d2,d3],(sp)
+	mov	d0,(12,sp)
+	mov	d1,(16,sp)
+	mov	(20,sp),d2			# count
+	add	d0,d2,a0			# dst end
+	add	d1,d2,a1			# src end
+	mov	d0,e3				# the return value
+
+	cmp	+0,d2
+	beq	memmove_done			# return if zero-length copy
+
+	# see if the three parameters are all four-byte aligned
+	or	d0,d1,d3
+	or	d2,d3
+	and	+3,d3
+	bne	memmove_1			# jump if not
+
+	# we want to transfer as much as we can in chunks of 32 bytes
+	add	-4,a1
+	cmp	+31,d2
+	bls	memmove_4_remainder		# 4-byte aligned remainder
+
+	add	-32,d2
+	mov	+32,d3
+
+memmove_4_loop:
+	mov	(a1),d0
+	sub_sub	+4,a1,+4,a0
+	mov	d0,(a0)
+	mov	(a1),d1
+	sub_sub	+4,a1,+4,a0
+	mov	d1,(a0)
+
+	mov	(a1),d0
+	sub_sub	+4,a1,+4,a0
+	mov	d0,(a0)
+	mov	(a1),d1
+	sub_sub	+4,a1,+4,a0
+	mov	d1,(a0)
+
+	mov	(a1),d0
+	sub_sub	+4,a1,+4,a0
+	mov	d0,(a0)
+	mov	(a1),d1
+	sub_sub	+4,a1,+4,a0
+	mov	d1,(a0)
+
+	mov	(a1),d0
+	sub_sub	+4,a1,+4,a0
+	mov	d0,(a0)
+	mov	(a1),d1
+	sub_sub	+4,a1,+4,a0
+	mov	d1,(a0)
+
+	sub	d3,d2
+	bcc	memmove_4_loop
+
+	add	d3,d2
+	beq	memmove_4_no_remainder
+
+memmove_4_remainder:
+	# cut 4-7 words down to 0-3
+	cmp	+16,d2
+	bcs	memmove_4_three_or_fewer_words
+	mov	(a1),d0
+	sub_sub	+4,a1,+4,a0
+	mov	d0,(a0)
+	mov	(a1),d1
+	sub_sub	+4,a1,+4,a0
+	mov	d1,(a0)
+	mov	(a1),e0
+	sub_sub	+4,a1,+4,a0
+	mov	e0,(a0)
+	mov	(a1),e1
+	sub_sub	+4,a1,+4,a0
+	mov	e1,(a0)
+	add	-16,d2
+	beq	memmove_4_no_remainder
+
+	# copy the remaining 1, 2 or 3 words
+memmove_4_three_or_fewer_words:
+	cmp	+8,d2
+	bcs	memmove_4_one_word
+	beq	memmove_4_two_words
+	mov	(a1),d0
+	sub_sub	+4,a1,+4,a0
+	mov	d0,(a0)
+memmove_4_two_words:
+	mov	(a1),d0
+	sub_sub	+4,a1,+4,a0
+	mov	d0,(a0)
+memmove_4_one_word:
+	mov	(a1),d0
+	sub_sub	+4,a1,+4,a0
+	mov	d0,(a0)
+
+memmove_4_no_remainder:
+	# check we copied the correct amount
+	# TODO: REMOVE CHECK
+	sub	e3,a0,d2
+	beq	memmove_done
+	break
+	break
+	break
+
+memmove_done:
+	mov	e3,a0
+	ret	[d2,d3],8
+
+	# handle misaligned copying
+memmove_1:
+	add	-1,a1
+	add	-1,d2
+	mov	+1,d3
+	setlb					# setlb requires the next insns
+						# to occupy exactly 4 bytes
+
+	sub	d3,d2
+	movbu	(a1),d0
+	sub_sub	d3,a1,d3,a0
+	movbu	d0,(a0)
+	lcc
+
+	mov	e3,a0
+	ret	[d2,d3],8
+
+memmove_memcpy:
+	jmp	memcpy
+
+memmove_end:
+	.size	memmove, memmove_end-memmove
diff --git a/arch/mn10300/lib/memset.S b/arch/mn10300/lib/memset.S
new file mode 100644
index 0000000..bc02e39
--- /dev/null
+++ b/arch/mn10300/lib/memset.S
@@ -0,0 +1,121 @@
+/* Optimised simple memory fill
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/cache.h>
+
+        .section .text
+        .balign	L1_CACHE_BYTES
+
+###############################################################################
+#
+# void *memset(void *dst, int c, size_t n)
+#
+###############################################################################
+	.globl	memset
+        .type	memset,@function
+memset:
+	movm	[d2,d3],(sp)
+	mov	d0,(12,sp)
+	mov	d1,(16,sp)
+	mov	(20,sp),d2			# count
+	mov	d0,a0				# dst
+	mov	d0,e3				# the return value
+
+	cmp	+0,d2
+	beq	memset_done			# return if zero-length fill
+
+	# see if the region parameters are four-byte aligned
+	or	d0,d2,d3
+	and	+3,d3
+	bne	memset_1			# jump if not
+
+	extbu	d1
+	mov_asl	d1,d3,8,d1
+	or_asl	d1,d3,8,d1
+	or_asl	d1,d3,8,d1
+	or	d3,d1
+
+	# we want to transfer as much as we can in chunks of 32 bytes
+	cmp	+31,d2
+	bls	memset_4_remainder		# 4-byte aligned remainder
+
+	add	-32,d2
+	mov	+32,d3
+
+memset_4_loop:
+	mov	d1,(a0+)
+	mov	d1,(a0+)
+	mov	d1,(a0+)
+	mov	d1,(a0+)
+	mov	d1,(a0+)
+	mov	d1,(a0+)
+	mov	d1,(a0+)
+	mov	d1,(a0+)
+
+	sub	d3,d2
+	bcc	memset_4_loop
+
+	add	d3,d2
+	beq	memset_4_no_remainder
+
+memset_4_remainder:
+	# cut 4-7 words down to 0-3
+	cmp	+16,d2
+	bcs	memset_4_three_or_fewer_words
+	mov	d1,(a0+)
+	mov	d1,(a0+)
+	mov	d1,(a0+)
+	mov	d1,(a0+)
+	add	-16,d2
+	beq	memset_4_no_remainder
+
+	# copy the remaining 1, 2 or 3 words
+memset_4_three_or_fewer_words:
+	cmp	+8,d2
+	bcs	memset_4_one_word
+	beq	memset_4_two_words
+	mov	d1,(a0+)
+memset_4_two_words:
+	mov	d1,(a0+)
+memset_4_one_word:
+	mov	d1,(a0+)
+
+memset_4_no_remainder:
+	# check we set the correct amount
+	# TODO: REMOVE CHECK
+	sub	e3,a0,d2
+	mov	(20,sp),d1
+	cmp	d2,d1
+	beq	memset_done
+	break
+	break
+	break
+
+memset_done:
+	mov	e3,a0
+	ret	[d2,d3],8
+
+	# handle misaligned copying
+memset_1:
+	add	-1,d2
+	mov	+1,d3
+	setlb					# setlb requires the next insns
+						# to occupy exactly 4 bytes
+
+	sub	d3,d2
+	movbu	d1,(a0)
+	inc	a0
+	lcc
+
+	mov	e3,a0
+	ret	[d2,d3],8
+
+memset_end:
+	.size	memset, memset_end-memset
diff --git a/arch/mn10300/lib/negdi2.c b/arch/mn10300/lib/negdi2.c
new file mode 100644
index 0000000..eae4ecd
--- /dev/null
+++ b/arch/mn10300/lib/negdi2.c
@@ -0,0 +1,57 @@
+/* More subroutines needed by GCC output code on some machines.  */
+/* Compile this one with gcc.  */
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+   2000, 2001  Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public Licence as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+In addition to the permissions in the GNU General Public Licence, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public Licence restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public Licence for more details.
+
+You should have received a copy of the GNU General Public Licence
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* It is incorrect to include config.h here, because this file is being
+   compiled for the target, and hence definitions concerning only the host
+   do not apply.  */
+
+#include <linux/types.h>
+
+union DWunion {
+	s64 ll;
+	struct {
+		s32 low;
+		s32 high;
+	} s;
+};
+
+s64 __negdi2(s64 u)
+{
+	union DWunion w;
+	union DWunion uu;
+
+	uu.ll = u;
+
+	w.s.low = -uu.s.low;
+	w.s.high = -uu.s.high - ((u32) w.s.low > 0);
+
+	return w.ll;
+}
diff --git a/arch/mn10300/lib/usercopy.c b/arch/mn10300/lib/usercopy.c
new file mode 100644
index 0000000..a75b203
--- /dev/null
+++ b/arch/mn10300/lib/usercopy.c
@@ -0,0 +1,166 @@
+/* MN10300 Userspace accessor functions
+ *
+ * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <asm/uaccess.h>
+
+unsigned long
+__generic_copy_to_user(void *to, const void *from, unsigned long n)
+{
+	if (access_ok(VERIFY_WRITE, to, n))
+		__copy_user(to, from, n);
+	return n;
+}
+
+unsigned long
+__generic_copy_from_user(void *to, const void *from, unsigned long n)
+{
+	if (access_ok(VERIFY_READ, from, n))
+		__copy_user_zeroing(to, from, n);
+	return n;
+}
+
+/*
+ * Copy a null terminated string from userspace.
+ */
+#define __do_strncpy_from_user(dst, src, count, res)		\
+do {								\
+	int w;							\
+	asm volatile(						\
+		"	mov	%1,%0\n"			\
+		"	cmp	0,%1\n"				\
+		"	beq	2f\n"				\
+		"0:\n"						\
+		"	movbu	(%5),%2\n"			\
+		"1:\n"						\
+		"	movbu	%2,(%6)\n"			\
+		"	inc	%5\n"				\
+		"	inc	%6\n"				\
+		"	cmp	0,%2\n"				\
+		"	beq	2f\n"				\
+		"	add	-1,%1\n"			\
+		"	bne	0b\n"				\
+		"2:\n"						\
+		"	sub	%1,%0\n"			\
+		"3:\n"						\
+		"	.section .fixup,\"ax\"\n"		\
+		"4:\n"						\
+		"	mov	%3,%0\n"			\
+		"	jmp	3b\n"				\
+		"	.previous\n"				\
+		"	.section __ex_table,\"a\"\n"		\
+		"	.balign 4\n"				\
+		"	.long 0b,4b\n"				\
+		"	.long 1b,4b\n"				\
+		"	.previous"				\
+		:"=&r"(res), "=r"(count), "=&r"(w)		\
+		:"i"(-EFAULT), "1"(count), "a"(src), "a"(dst)	\
+		:"memory");					\
+} while (0)
+
+long
+__strncpy_from_user(char *dst, const char *src, long count)
+{
+	long res;
+	__do_strncpy_from_user(dst, src, count, res);
+	return res;
+}
+
+long
+strncpy_from_user(char *dst, const char *src, long count)
+{
+	long res = -EFAULT;
+	if (access_ok(VERIFY_READ, src, 1))
+		__do_strncpy_from_user(dst, src, count, res);
+	return res;
+}
+
+
+/*
+ * Clear a userspace memory
+ */
+#define __do_clear_user(addr, size)		\
+do {						\
+	int w;					\
+	asm volatile(				\
+		"	cmp 0,%0\n"		\
+		"	beq 1f\n"		\
+		"	clr %1\n"		\
+		"0:	movbu %1,(%3,%2)\n"	\
+		"	inc %3\n"		\
+		"	cmp %0,%3\n"		\
+		"	bne 0b\n"		\
+		"1:\n"				\
+		"	sub %3,%0\n"		\
+		"2:\n"				\
+		".section .fixup,\"ax\"\n"	\
+		"3:	jmp 2b\n"		\
+		".previous\n"			\
+		".section __ex_table,\"a\"\n"	\
+		"       .balign 4\n"		\
+		"       .long 0b,3b\n"		\
+		".previous\n"			\
+		: "+r"(size), "=&r"(w)		\
+		: "a"(addr), "d"(0)		\
+		: "memory");			\
+} while (0)
+
+unsigned long
+__clear_user(void *to, unsigned long n)
+{
+	__do_clear_user(to, n);
+	return n;
+}
+
+unsigned long
+clear_user(void *to, unsigned long n)
+{
+	if (access_ok(VERIFY_WRITE, to, n))
+		__do_clear_user(to, n);
+	return n;
+}
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 on exception, a value greater than N if too long
+ */
+long strnlen_user(const char *s, long n)
+{
+	unsigned long res, w;
+
+	if (!__addr_ok(s))
+		return 0;
+
+	if (n < 0 || n + (u_long) s > current_thread_info()->addr_limit.seg)
+		n = current_thread_info()->addr_limit.seg - (u_long)s;
+
+	asm volatile(
+		"0:	cmp %4,%0\n"
+		"	beq 2f\n"
+		"1:	movbu (%0,%3),%1\n"
+		"	inc %0\n"
+		"	cmp 0,%1\n"
+		"	beq 3f\n"
+		"	bra 0b\n"
+		"2:	clr %0\n"
+		"3:\n"
+		".section .fixup,\"ax\"\n"
+		"4:	jmp 2b\n"
+		".previous\n"
+		".section __ex_table,\"a\"\n"
+		"	.balign 4\n"
+		"	.long 1b,4b\n"
+		".previous\n"
+		:"=d"(res), "=&r"(w)
+		:"0"(0), "a"(s), "r"(n)
+		:"memory");
+	return res;
+}