File-copy from v4.4.100

This is the result of 'cp' from a linux-stable tree with the 'v4.4.100'
tag checked out (commit 26d6298789e695c9f627ce49a7bbd2286405798a) on
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git

Please refer to that tree for all history prior to this point.

Change-Id: I8a9ee2aea93cd29c52c847d0ce33091a73ae6afe
diff --git a/arch/mn10300/lib/Makefile b/arch/mn10300/lib/Makefile
new file mode 100644
index 0000000..0cd2346
--- /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 __ucmpdi2.o
diff --git a/arch/mn10300/lib/__ashldi3.S b/arch/mn10300/lib/__ashldi3.S
new file mode 100644
index 0000000..a51a950
--- /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/__ucmpdi2.S b/arch/mn10300/lib/__ucmpdi2.S
new file mode 100644
index 0000000..60dcbdf
--- /dev/null
+++ b/arch/mn10300/lib/__ucmpdi2.S
@@ -0,0 +1,43 @@
+/* __ucmpdi2.S: 64-bit unsigned compare
+ *
+ * Copyright (C) 2008 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 License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+
+        .text
+        .p2align	4
+
+###############################################################################
+#
+# int __ucmpdi2(unsigned long long a [D0:D1],
+#		unsigned long long b [(SP,12),(SP,16)])
+#
+# - returns 0, 1, or 2 as a <, =, > b respectively.
+#
+###############################################################################
+        .globl		__ucmpdi2
+        .type		__ucmpdi2,@function
+__ucmpdi2:
+	mov		(12,sp),a0		# b.lsw
+	mov		(16,sp),a1		# b.msw
+
+	sub		a0,d0
+	subc		a1,d1			# may clear Z, never sets it
+	bne		__ucmpdi2_differ	# a.msw != b.msw
+	mov		+1,d0
+	rets
+
+__ucmpdi2_differ:
+	# C flag is set if LE, clear if GE
+	subc		d0,d0			# -1 if LE, 0 if GE
+	add		+1,d0			#  0 if LE, 1 if GE
+	add		d0,d0			#  0 if LE, 2 if GE
+	rets
+
+	.size		__ucmpdi2, .-__ucmpdi2
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..37309cd
--- /dev/null
+++ b/arch/mn10300/lib/bitops.c
@@ -0,0 +1,50 @@
+/* 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>
+
+/*
+ * try flipping a bit using BSET and BCLR
+ */
+void change_bit(unsigned long 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(unsigned long 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..b6580f5
--- /dev/null
+++ b/arch/mn10300/lib/checksum.c
@@ -0,0 +1,100 @@
+/* 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)
+	    : "cc"
+	    );
+	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..8e7ceb8
--- /dev/null
+++ b/arch/mn10300/lib/delay.c
@@ -0,0 +1,51 @@
+/* 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)
+		: "cc");
+}
+EXPORT_SYMBOL(__delay);
+
+/*
+ * handle a delay specified in terms of microseconds
+ */
+void __udelay(unsigned long usecs)
+{
+	unsigned long start, stop, cnt;
+
+	/* usecs * CLK / 1E6 */
+	stop = __muldiv64u(usecs, MN10300_TSCCLK, 1000000);
+	start = TMTSCBC;
+
+	do {
+		cnt = start - TMTSCBC;
+	} while (cnt < stop);
+}
+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..1d27bba
--- /dev/null
+++ b/arch/mn10300/lib/do_csum.S
@@ -0,0 +1,157 @@
+/* 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, int len)
+#
+###############################################################################
+	.globl	do_csum
+	.type	do_csum,@function
+do_csum:
+	movm	[d2,d3],(sp)
+	mov	d1,d2				# count
+	mov	d0,a0				# buff
+	mov	a0,a1
+	clr	d1				# accumulator
+
+	cmp	+0,d2
+	ble	do_csum_done			# check for zero length or negative
+
+	# 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
+	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
+	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
+	mov	(a0+),e0
+	mov	(a0+),e1
+	mov	(a0+),e3
+	add	d0,d1
+	addc	e0,d1
+	addc	e1,d1
+	addc	e3,d1
+	mov	(a0+),d0
+	mov	(a0+),e0
+	mov	(a0+),e1
+	mov	(a0+),e3
+	addc	d0,d1
+	addc	e0,d1
+	addc	e1,d1
+	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
+	mov	(a0+),e0
+	mov	(a0+),e1
+	mov	(a0+),e3
+	add	d0,d1
+	addc	e0,d1
+	addc	e1,d1
+	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
+	and	+1,d2
+	beq	do_csum_add_last_bit
+do_csum_fewer_than_2:
+	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,d0
+	and	d1,d0
+	asl	+16,d1
+	add	d1,d0
+	addc	+0xffff,d0
+	lsr	+16,d0
+
+	# flip the halves of the word result if the buffer was oddly aligned
+	and	+1,a1
+	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
+
+	.size	do_csum, .-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..ce8899e
--- /dev/null
+++ b/arch/mn10300/lib/usercopy.c
@@ -0,0 +1,168 @@
+/* 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 <linux/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);
+	else
+		memset(to, 0, 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", "cc");					\
+} 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", "cc");		\
+} 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", "cc");
+	return res;
+}