Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
diff --git a/arch/m32r/lib/Makefile b/arch/m32r/lib/Makefile
new file mode 100644
index 0000000..e632d10
--- /dev/null
+++ b/arch/m32r/lib/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for M32R-specific library files..
+#
+
+lib-y  := checksum.o ashxdi3.o memset.o memcpy.o getuser.o \
+	  putuser.o delay.o strlen.o usercopy.o csum_partial_copy.o
+
diff --git a/arch/m32r/lib/ashxdi3.S b/arch/m32r/lib/ashxdi3.S
new file mode 100644
index 0000000..78effca
--- /dev/null
+++ b/arch/m32r/lib/ashxdi3.S
@@ -0,0 +1,297 @@
+/*
+ * linux/arch/m32r/lib/ashxdi3.S
+ *
+ * Copyright (C) 2001,2002  Hiroyuki Kondo, and Hirokazu Takata
+ *
+ */
+/* $Id$ */
+
+#include <linux/config.h>
+
+;
+;      input   (r0,r1)  src
+;      input    r2      shift val
+;               r3      scratch
+;      output  (r0,r1)
+;
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+#ifndef __LITTLE_ENDIAN__
+
+	.text
+	.align	4
+	.globl __ashrdi3
+__ashrdi3:
+	cmpz	r2		    ||	ldi	r3, #32
+	jc	r14		    ||	cmpu	r2, r3
+	bc      1f
+    ;   case 32 =< shift
+	mv      r1, r0		    ||	srai    r0, #31
+	addi    r2, #-32
+	sra     r1, r2
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r0		    ||	srl     r1, r2
+	sra     r0, r2		    ||	neg     r2, r2
+	sll     r3, r2
+	or      r1, r3		    ||	jmp	r14
+
+        .align  4
+        .globl __ashldi3
+        .globl __lshldi3
+__ashldi3:
+__lshldi3:
+	cmpz	r2		    ||	ldi	r3, #32
+	jc	r14		    ||	cmpu	r2, r3
+	bc      1f
+    ;   case 32 =< shift
+	mv      r0, r1		    ||	addi    r2, #-32
+	sll     r0, r2		    ||	ldi     r1, #0
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r1		    ||	sll     r0, r2
+	sll     r1, r2		    ||	neg     r2, r2
+	srl     r3, r2
+	or      r0, r3		    ||	jmp	r14
+
+	.align	4
+	.globl __lshrdi3
+__lshrdi3:
+	cmpz	r2		    ||	ldi	r3, #32
+	jc	r14		    ||	cmpu	r2, r3
+	bc      1f
+    ;   case 32 =< shift
+	mv      r1, r0		    ||	addi    r2, #-32
+	ldi	r0, #0		    ||	srl     r1, r2
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r0		    ||	srl     r1, r2
+	srl     r0, r2		    ||	neg     r2, r2
+	sll     r3, r2
+	or      r1, r3		    ||	jmp	r14
+
+#else /* LITTLE_ENDIAN */
+
+	.text
+	.align	4
+	.globl __ashrdi3
+__ashrdi3:
+	cmpz	r2		    ||	ldi	r3, #32
+	jc	r14		    ||	cmpu	r2, r3
+	bc      1f
+    ;   case 32 =< shift
+	mv      r0, r1		    ||	srai    r1, #31
+	addi    r2, #-32
+	sra     r0, r2
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r1		    ||	srl     r0, r2
+	sra     r1, r2		    ||	neg     r2, r2
+	sll     r3, r2
+	or      r0, r3		    ||	jmp	r14
+
+        .align  4
+        .globl __ashldi3
+        .globl __lshldi3
+__ashldi3:
+__lshldi3:
+	cmpz	r2		    ||	ldi	r3, #32
+	jc	r14		    ||	cmpu	r2, r3
+	bc      1f
+    ;   case 32 =< shift
+	mv      r1, r0		    ||	addi    r2, #-32
+	sll     r1, r2		    ||	ldi     r0, #0
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r0		    ||	sll     r1, r2
+	sll     r0, r2		    ||	neg     r2, r2
+	srl     r3, r2
+	or      r1, r3		    ||	jmp	r14
+
+	.align	4
+	.globl __lshrdi3
+__lshrdi3:
+	cmpz	r2		    ||	ldi	r3, #32
+	jc	r14		    ||	cmpu	r2, r3
+	bc      1f
+    ;   case 32 =< shift
+	mv      r0, r1		    ||	addi    r2, #-32
+	ldi	r1, #0		    ||	srl     r0, r2
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r1		    ||	srl     r0, r2
+	srl     r1, r2		    ||	neg     r2, r2
+	sll     r3, r2
+	or      r0, r3		    ||	jmp	r14
+
+#endif
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+#ifndef __LITTLE_ENDIAN__
+
+	.text
+	.align	4
+	.globl __ashrdi3
+__ashrdi3:
+	beqz	r2, 2f
+	cmpui   r2, #32
+	bc      1f
+    ;   case 32 =< shift
+	mv      r1, r0
+	srai    r0, #31
+	addi    r2, #-32
+	sra     r1, r2
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r0
+	srl     r1, r2
+	sra     r0, r2
+	neg     r2, r2
+	sll     r3, r2
+	or      r1, r3
+	.fillinsn
+2:
+	jmp	r14
+
+        .align  4
+        .globl __ashldi3
+        .globl __lshldi3
+__ashldi3:
+__lshldi3:
+	beqz	r2, 2f
+	cmpui   r2, #32
+	bc      1f
+    ;   case 32 =< shift
+	mv      r0, r1
+	addi    r2, #-32
+	sll     r0, r2
+	ldi     r1, #0
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r1
+	sll     r0, r2
+	sll     r1, r2
+	neg     r2, r2
+	srl     r3, r2
+	or      r0, r3
+	.fillinsn
+2:
+	jmp	r14
+
+	.align	4
+	.globl __lshrdi3
+__lshrdi3:
+	beqz	r2, 2f
+	cmpui   r2, #32
+	bc      1f
+    ;   case 32 =< shift
+	mv      r1, r0
+	ldi	r0, #0
+	addi    r2, #-32
+	srl     r1, r2
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r0
+	srl     r1, r2
+	srl     r0, r2
+	neg     r2, r2
+	sll     r3, r2
+	or      r1, r3
+	.fillinsn
+2:
+	jmp	r14
+
+#else
+
+	.text
+	.align	4
+	.globl __ashrdi3
+__ashrdi3:
+	beqz	r2, 2f
+	cmpui   r2, #32
+	bc      1f
+    ;   case 32 =< shift
+	mv      r0, r1
+	srai    r1, #31
+	addi    r2, #-32
+	sra     r0, r2
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r1
+	srl     r0, r2
+	sra     r1, r2
+	neg     r2, r2
+	sll     r3, r2
+	or      r0, r3
+	.fillinsn
+2:
+	jmp	r14
+
+        .align  4
+        .globl __ashldi3
+        .globl __lshldi3
+__ashldi3:
+__lshldi3:
+	beqz	r2, 2f
+	cmpui   r2, #32
+	bc      1f
+    ;   case 32 =< shift
+	mv      r1, r0
+	addi    r2, #-32
+	sll     r1, r2
+	ldi     r0, #0
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r0
+	sll     r1, r2
+	sll     r0, r2
+	neg     r2, r2
+	srl     r3, r2
+	or      r1, r3
+	.fillinsn
+2:
+	jmp	r14
+
+	.align	4
+	.globl __lshrdi3
+__lshrdi3:
+	beqz	r2, 2f
+	cmpui   r2, #32
+	bc      1f
+    ;   case 32 =< shift
+	mv      r0, r1
+	ldi	r1, #0
+	addi    r2, #-32
+	srl     r0, r2
+	jmp     r14
+	.fillinsn
+1:  ;   case shift <32
+	mv      r3, r1
+	srl     r0, r2
+	srl     r1, r2
+	neg     r2, r2
+	sll     r3, r2
+	or      r0, r3
+	.fillinsn
+2:
+	jmp	r14
+
+#endif
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+	.end
+
diff --git a/arch/m32r/lib/checksum.S b/arch/m32r/lib/checksum.S
new file mode 100644
index 0000000..f6fc1bd
--- /dev/null
+++ b/arch/m32r/lib/checksum.S
@@ -0,0 +1,322 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		IP/TCP/UDP checksumming routines
+ *
+ * Authors:	Jorge Cwik, <jorge@laser.satlink.net>
+ *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ *		Tom May, <ftom@netcom.com>
+ *              Pentium Pro/II routines:
+ *              Alexander Kjeldaas <astor@guardian.no>
+ *              Finn Arne Gangstad <finnag@guardian.no>
+ *		Lots of code moved from tcp.c and ip.c; see those files
+ *		for more names.
+ *
+ * Changes:     Ingo Molnar, converted csum_partial_copy() to 2.1 exception
+ *			     handling.
+ *		Andi Kleen,  add zeroing on error
+ *                   converted to pure assembler
+ *		Hirokazu Takata,Hiroyuki Kondo rewrite for the m32r architecture.
+ *
+ *		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.
+ */
+/* $Id$ */
+
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/errno.h>
+
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+
+/*
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+ */
+
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+	/*
+	 * Experiments with Ethernet and SLIP connections show that buff
+	 * is aligned on either a 2-byte or 4-byte boundary.  We get at
+	 * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
+	 * Fortunately, it is easy to convert 2-byte alignment to 4-byte
+	 * alignment for the unrolled loop.
+	 */
+
+	.text
+ENTRY(csum_partial)
+	; Function args
+	;  r0: unsigned char *buff
+	;  r1: int len
+	;  r2: unsigned int sum
+
+	push	r2		    ||	ldi	r2, #0
+	and3	r7, r0, #1		; Check alignment.
+	beqz	r7, 1f	 		; Jump if alignment is ok.
+	; 1-byte mis aligned
+	ldub	r4, @r0		    ||	addi	r0, #1
+	; clear c-bit || Alignment uses up bytes.
+	cmp	r0, r0		    ||	addi	r1, #-1
+	ldi	r3, #0		    ||	addx	r2, r4
+	addx	r2, r3
+	.fillinsn
+1:
+	and3	r4, r0, #2		; Check alignment.
+	beqz	r4, 2f	 		; Jump if alignment is ok.
+	; clear c-bit || Alignment uses up two bytes.
+	cmp	r0, r0		    ||	addi	r1, #-2
+	bgtz	r1, 1f			; Jump if we had at least two bytes.
+	bra	4f		    ||	addi	r1, #2
+	.fillinsn			; len(r1) was < 2.  Deal with it.
+1:
+	; 2-byte aligned
+	lduh	r4, @r0		    ||	ldi	r3, #0
+	addx	r2, r4		    ||	addi	r0, #2
+	addx	r2, r3
+	.fillinsn
+2:
+	; 4-byte aligned
+	cmp	r0, r0			; clear c-bit
+	srl3	r6, r1, #5
+	beqz	r6, 2f
+	.fillinsn
+
+1:	ld	r3, @r0+
+	ld	r4, @r0+					; +4
+	ld	r5, @r0+					; +8
+	ld	r3, @r0+	    ||	addx    r2, r3		; +12
+	ld	r4, @r0+	    ||	addx    r2, r4		; +16
+	ld	r5, @r0+	    ||	addx    r2, r5		; +20
+	ld	r3, @r0+	    ||	addx    r2, r3		; +24
+	ld	r4, @r0+	    ||	addx    r2, r4		; +28
+	addx	r2, r5		    ||	addi	r6, #-1
+	addx	r2, r3
+	addx	r2, r4
+	bnez	r6, 1b
+
+	addx	r2, r6			; r6=0
+	cmp	r0, r0			; This clears c-bit
+	.fillinsn
+2:	and3	r6, r1, #0x1c		; withdraw len
+	beqz	r6, 4f
+	srli	r6, #2
+	.fillinsn
+
+3:	ld	r4, @r0+	    ||	addi	r6, #-1
+	addx	r2, r4
+	bnez	r6, 3b
+
+	addx	r2, r6			; r6=0
+	cmp	r0, r0			; This clears c-bit
+	.fillinsn
+4:	and3	r1, r1, #3
+	beqz	r1, 7f			; if len == 0 goto end
+	and3	r6, r1, #2
+	beqz	r6, 5f			; if len < 2  goto 5f(1byte)
+	lduh	r4, @r0		    ||	addi	r0, #2
+	addi	r1, #-2		    ||	slli    r4, #16
+	addx	r2, r4
+	beqz	r1, 6f
+	.fillinsn
+5:	ldub	r4, @r0		    ||	ldi	r1, #0
+#ifndef __LITTLE_ENDIAN__
+	slli    r4, #8
+#endif
+	addx	r2, r4
+	.fillinsn
+6:	addx	r2, r1
+	.fillinsn
+7:
+	and3	r0, r2, #0xffff
+	srli	r2, #16
+	add	r0, r2
+	srl3	r2, r0, #16
+	beqz	r2, 1f
+	addi	r0, #1
+	and3	r0, r0, #0xffff
+	.fillinsn
+1:
+	beqz	r7, 1f			; swap the upper byte for the lower
+	and3	r2, r0, #0xff
+	srl3	r0, r0, #8
+	slli	r2, #8
+	or	r0, r2
+	.fillinsn
+1:
+	pop	r2		    ||	cmp	r0, r0
+	addx	r0, r2		    ||	ldi	r2, #0
+	addx	r0, r2
+	jmp	r14
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+	/*
+	 * Experiments with Ethernet and SLIP connections show that buff
+	 * is aligned on either a 2-byte or 4-byte boundary.  We get at
+	 * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
+	 * Fortunately, it is easy to convert 2-byte alignment to 4-byte
+	 * alignment for the unrolled loop.
+	 */
+
+	.text
+ENTRY(csum_partial)
+	; Function args
+	;  r0: unsigned char *buff
+	;  r1: int len
+	;  r2: unsigned int sum
+
+	push	r2
+	ldi	r2, #0
+	and3	r7, r0, #1		; Check alignment.
+	beqz	r7, 1f	 		; Jump if alignment is ok.
+	; 1-byte mis aligned
+	ldub	r4, @r0
+	addi	r0, #1
+	addi	r1, #-1			; Alignment uses up bytes.
+	cmp	r0, r0			; clear c-bit
+	ldi	r3, #0
+	addx	r2, r4
+	addx	r2, r3
+	.fillinsn
+1:
+	and3	r4, r0, #2		; Check alignment.
+	beqz	r4, 2f	 		; Jump if alignment is ok.
+	addi	r1, #-2			; Alignment uses up two bytes.
+	cmp		r0, r0			; clear c-bit
+	bgtz	r1, 1f			; Jump if we had at least two bytes.
+	addi	r1, #2			; len(r1) was < 2.  Deal with it.
+	bra	4f
+	.fillinsn
+1:
+	; 2-byte aligned
+	lduh	r4, @r0
+	addi	r0, #2
+	ldi		r3, #0
+	addx	r2, r4
+	addx	r2, r3
+	.fillinsn
+2:
+	; 4-byte aligned
+	cmp	r0, r0			; clear c-bit
+	srl3	r6, r1, #5
+	beqz	r6, 2f
+	.fillinsn
+
+1:	ld	r3, @r0+
+	ld	r4, @r0+		; +4
+	ld	r5, @r0+		; +8
+	addx	r2, r3
+	addx	r2, r4
+	addx	r2, r5
+	ld	r3, @r0+		; +12
+	ld	r4, @r0+		; +16
+	ld	r5, @r0+		; +20
+	addx	r2, r3
+	addx	r2, r4
+	addx	r2, r5
+	ld	r3, @r0+		; +24
+	ld	r4, @r0+		; +28
+	addi	r6, #-1
+	addx	r2, r3
+	addx	r2, r4
+	bnez	r6, 1b
+	addx	r2, r6			; r6=0
+	cmp	r0, r0			; This clears c-bit
+	.fillinsn
+
+2:	and3	r6, r1, #0x1c		; withdraw len
+	beqz	r6, 4f
+	srli	r6, #2
+	.fillinsn
+
+3:	ld	r4, @r0+
+	addi	r6, #-1
+	addx	r2, r4
+	bnez	r6, 3b
+	addx	r2, r6			; r6=0
+	cmp	r0, r0			; This clears c-bit
+	.fillinsn
+
+4:	and3	r1, r1, #3
+	beqz	r1, 7f			; if len == 0 goto end
+	and3	r6, r1, #2
+	beqz	r6, 5f			; if len < 2  goto 5f(1byte)
+
+	lduh	r4, @r0
+	addi	r0, #2
+	addi	r1, #-2
+	slli    r4, #16
+	addx	r2, r4
+	beqz	r1, 6f
+	.fillinsn
+5:	ldub	r4, @r0
+#ifndef __LITTLE_ENDIAN__
+	slli    r4, #8
+#endif
+	addx	r2, r4
+	.fillinsn
+6:	ldi	r5, #0
+	addx	r2, r5
+	.fillinsn
+7:
+	and3	r0, r2, #0xffff
+	srli	r2, #16
+	add	r0, r2
+	srl3	r2, r0, #16
+	beqz	r2, 1f
+	addi	r0, #1
+	and3	r0, r0, #0xffff
+	.fillinsn
+1:
+	beqz	r7, 1f
+	mv	r2, r0
+	srl3	r0, r2, #8
+	and3	r2, r2, #0xff
+	slli	r2, #8
+	or	r0, r2
+	.fillinsn
+1:
+	pop	r2
+	cmp	r0, r0
+	addx	r0, r2
+	ldi	r2, #0
+	addx	r0, r2
+	jmp	r14
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+/*
+unsigned int csum_partial_copy_generic (const char *src, char *dst,
+				  int len, int sum, int *src_err_ptr, int *dst_err_ptr)
+ */
+
+/*
+ * Copy from ds while checksumming, otherwise like csum_partial
+ *
+ * The macros SRC and DST specify the type of access for the instruction.
+ * thus we can call a custom exception handler for all access types.
+ *
+ * FIXME: could someone double-check whether I haven't mixed up some SRC and
+ *	  DST definitions? It's damn hard to trigger all cases.  I hope I got
+ *	  them all but there's no guarantee.
+ */
+
+ENTRY(csum_partial_copy_generic)
+	nop
+	nop
+	nop
+	nop
+	jmp r14
+	nop
+	nop
+	nop
+
diff --git a/arch/m32r/lib/csum_partial_copy.c b/arch/m32r/lib/csum_partial_copy.c
new file mode 100644
index 0000000..c871b46
--- /dev/null
+++ b/arch/m32r/lib/csum_partial_copy.c
@@ -0,0 +1,60 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		M32R specific IP/TCP/UDP checksumming routines
+ *		(Some code taken from MIPS architecture)
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994, 1995  Waldorf Electronics GmbH
+ * Copyright (C) 1998, 1999  Ralf Baechle
+ * Copyright (C) 2001-2005  Hiroyuki Kondo, Hirokazu Takata
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+
+#include <net/checksum.h>
+#include <asm/byteorder.h>
+#include <asm/string.h>
+#include <asm/uaccess.h>
+
+/*
+ * Copy while checksumming, otherwise like csum_partial
+ */
+unsigned int
+csum_partial_copy_nocheck (const unsigned char *src, unsigned char *dst,
+                           int len, unsigned int sum)
+{
+	sum = csum_partial(src, len, sum);
+	memcpy(dst, src, len);
+
+	return sum;
+}
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
+
+/*
+ * Copy from userspace and compute checksum.  If we catch an exception
+ * then zero the rest of the buffer.
+ */
+unsigned int
+csum_partial_copy_from_user (const unsigned char __user *src,
+			     unsigned char *dst,
+			     int len, unsigned int 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-missing, sum);
+}
+EXPORT_SYMBOL(csum_partial_copy_from_user);
diff --git a/arch/m32r/lib/delay.c b/arch/m32r/lib/delay.c
new file mode 100644
index 0000000..fb29632
--- /dev/null
+++ b/arch/m32r/lib/delay.c
@@ -0,0 +1,126 @@
+/*
+ * linux/arch/m32r/lib/delay.c
+ *
+ * Copyright (c) 2002  Hitoshi Yamamoto, Hirokazu Takata
+ * Copyright (c) 2004  Hirokazu Takata
+ */
+
+/* $Id$ */
+
+#include <linux/config.h>
+#include <linux/param.h>
+#ifdef CONFIG_SMP
+#include <linux/sched.h>
+#include <asm/current.h>
+#include <asm/smp.h>
+#endif  /* CONFIG_SMP */
+#include <asm/processor.h>
+
+void __delay(unsigned long loops)
+{
+#ifdef CONFIG_ISA_DUAL_ISSUE
+	__asm__ __volatile__ (
+		"beqz	%0, 2f			\n\t"
+		"addi	%0, #-1			\n\t"
+
+		" .fillinsn			\n\t"
+		"1:				\n\t"
+		"cmpz	%0  ||  addi  %0, #-1	\n\t"
+		"bc	2f  ||  cmpz  %0	\n\t"
+		"bc	2f  ||  addi  %0, #-1	\n\t"
+		"cmpz	%0  ||  addi  %0, #-1	\n\t"
+		"bc	2f  ||  cmpz  %0	\n\t"
+		"bnc	1b  ||  addi  %0, #-1	\n\t"
+		" .fillinsn			\n\t"
+		"2:				\n\t"
+		: "+r" (loops)
+		: "r" (0)
+		: "cbit"
+	);
+#else
+	__asm__ __volatile__ (
+		"beqz	%0, 2f			\n\t"
+		" .fillinsn			\n\t"
+		"1:				\n\t"
+		"addi	%0, #-1			\n\t"
+		"blez	%0, 2f			\n\t"
+		"addi	%0, #-1			\n\t"
+		"blez	%0, 2f			\n\t"
+		"addi	%0, #-1			\n\t"
+		"blez	%0, 2f			\n\t"
+		"addi	%0, #-1			\n\t"
+		"bgtz	%0, 1b			\n\t"
+		" .fillinsn			\n\t"
+		"2:				\n\t"
+		: "+r" (loops)
+		: "r" (0)
+	);
+#endif
+}
+
+void __const_udelay(unsigned long xloops)
+{
+#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
+	/*
+	 * loops [1] = (xloops >> 32) [sec] * loops_per_jiffy [1/jiffy]
+	 *            * HZ [jiffy/sec]
+	 *          = (xloops >> 32) [sec] * (loops_per_jiffy * HZ) [1/sec]
+	 *          = (((xloops * loops_per_jiffy) >> 32) * HZ) [1]
+	 *
+	 * NOTE:
+	 *   - '[]' depicts variable's dimension in the above equation.
+	 *   - "rac" instruction rounds the accumulator in word size.
+	 */
+	__asm__ __volatile__ (
+		"srli	%0, #1				\n\t"
+		"mulwhi	%0, %1	; a0			\n\t"
+		"mulwu1	%0, %1	; a1			\n\t"
+		"sadd		; a0 += (a1 >> 16)	\n\t"
+		"rac	a0, a0, #1			\n\t"
+		"mvfacmi %0, a0				\n\t"
+		: "+r" (xloops)
+		: "r" (current_cpu_data.loops_per_jiffy)
+		: "a0", "a1"
+	);
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+	/*
+	 * u64 ull;
+	 * ull = (u64)xloops * (u64)current_cpu_data.loops_per_jiffy;
+	 * xloops = (ull >> 32);
+	 */
+	__asm__ __volatile__ (
+		"and3	r4, %0, #0xffff		\n\t"
+		"and3	r5, %1, #0xffff		\n\t"
+		"mul	r4, r5			\n\t"
+		"srl3	r6, %0, #16		\n\t"
+		"srli	r4, #16			\n\t"
+		"mul	r5, r6			\n\t"
+		"add	r4, r5			\n\t"
+		"and3	r5, %0, #0xffff		\n\t"
+		"srl3	r6, %1, #16		\n\t"
+		"mul	r5, r6			\n\t"
+		"add	r4, r5			\n\t"
+		"srl3	r5, %0, #16		\n\t"
+		"srli	r4, #16			\n\t"
+		"mul	r5, r6			\n\t"
+		"add	r4, r5			\n\t"
+		"mv	%0, r4			\n\t"
+		: "+r" (xloops)
+		: "r" (current_cpu_data.loops_per_jiffy)
+		: "r4", "r5", "r6"
+	);
+#else
+#error unknown isa configuration
+#endif
+	__delay(xloops * HZ);
+}
+
+void __udelay(unsigned long usecs)
+{
+	__const_udelay(usecs * 0x000010c7);  /* 2**32 / 1000000 (rounded up) */
+}
+
+void __ndelay(unsigned long nsecs)
+{
+	__const_udelay(nsecs * 0x00005);  /* 2**32 / 1000000000 (rounded up) */
+}
diff --git a/arch/m32r/lib/getuser.S b/arch/m32r/lib/getuser.S
new file mode 100644
index 0000000..58a0db0
--- /dev/null
+++ b/arch/m32r/lib/getuser.S
@@ -0,0 +1,88 @@
+/*
+ * __get_user functions.
+ *
+ * (C) Copyright 2001 Hirokazu Takata
+ *
+ * These functions have a non-standard call interface
+ * to make them more efficient, especially as they
+ * return an error value in addition to the "real"
+ * return value.
+ */
+
+#include <linux/config.h>
+
+/*
+ * __get_user_X
+ *
+ * Inputs:	r0 contains the address
+ *
+ * Outputs:	r0 is error code (0 or -EFAULT)
+ *		r1 contains zero-extended value
+ *
+ * These functions should not modify any other registers,
+ * as they get called from within inline assembly.
+ */
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+	.text
+	.balign 4
+	.globl __get_user_1
+__get_user_1:
+1:	ldub	r1, @r0		    ||	ldi	r0, #0
+	jmp	r14
+
+	.balign 4
+	.globl __get_user_2
+__get_user_2:
+2:	lduh	r1, @r0		    ||	ldi	r0, #0
+	jmp	r14
+
+	.balign 4
+	.globl __get_user_4
+__get_user_4:
+3:	ld	r1, @r0		    ||	ldi	r0, #0
+	jmp	r14
+
+bad_get_user:
+	ldi	r1, #0		    ||	ldi	r0, #-14
+	jmp	r14
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+	.text
+	.balign 4
+	.globl __get_user_1
+__get_user_1:
+1:	ldub	r1, @r0
+	ldi	r0, #0
+	jmp	r14
+
+	.balign 4
+	.globl __get_user_2
+__get_user_2:
+2:	lduh	r1, @r0
+	ldi	r0, #0
+	jmp	r14
+
+	.balign 4
+	.globl __get_user_4
+__get_user_4:
+3:	ld	r1, @r0
+	ldi	r0, #0
+	jmp	r14
+
+bad_get_user:
+	ldi	r1, #0
+	ldi	r0, #-14
+	jmp	r14
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+.section __ex_table,"a"
+	.long 1b,bad_get_user
+	.long 2b,bad_get_user
+	.long 3b,bad_get_user
+.previous
+
+	.end
diff --git a/arch/m32r/lib/memcpy.S b/arch/m32r/lib/memcpy.S
new file mode 100644
index 0000000..800898a
--- /dev/null
+++ b/arch/m32r/lib/memcpy.S
@@ -0,0 +1,95 @@
+/*
+ *  linux/arch/m32r/lib/memcpy.S
+ *
+ *  Copyright (C) 2001  Hiroyuki Kondo, and Hirokazu Takata
+ *  Copyright (C) 2004  Hirokazu Takata
+ *
+ *  void *memcopy(void *dst, const void *src, int n);
+ *
+ *        dst: r0
+ *        src: r1
+ *        n  : r2
+ */
+/* $Id$ */
+
+
+	.text
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+	.text
+ENTRY(memcpy)
+memcopy:
+	mv	r4, r0		    ||	mv	r7, r0
+	or	r7, r1		    ||	cmpz	r2
+	jc	r14		    ||	cmpeq	r0, r1	; return if r2=0
+	jc	r14					; return if r0=r1
+
+	and3	r7, r7, #3
+	bnez	r7, byte_copy
+	srl3	r3, r2, #2
+	and3	r2, r2, #3
+	beqz	r3, byte_copy
+	addi	r4, #-4
+word_copy:
+	ld	r7, @r1+	    ||	addi	r3, #-1
+	st	r7, @+r4	    ||	cmpz	r2
+	bnez	r3, word_copy
+	addi	r4, #4		    ||	jc	r14	; return if r2=0
+#if defined(CONFIG_ISA_M32R2)
+byte_copy:
+	ldb	r7, @r1		    ||	addi	r1, #1
+	addi	r2, #-1		    ||	stb	r7, @r4+
+	bnez	r2, byte_copy
+#elif defined(CONFIG_ISA_M32R)
+byte_copy:
+	ldb	r7, @r1		    ||	addi	r1, #1
+	addi	r2, #-1		    ||	stb	r7, @r4
+	addi	r4, #1
+	bnez	r2, byte_copy
+#else
+#error unknown isa configuration
+#endif
+end_memcopy:
+	jmp	r14
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+	.text
+ENTRY(memcpy)
+memcopy:
+	mv	r4, r0
+	mv	r7, r0
+	or	r7, r1
+	beq	r0, r1, end_memcopy
+	beqz	r2, end_memcopy
+
+	and3	r7, r7, #3
+	bnez	r7, byte_copy
+	srl3	r3, r2, #2
+	and3	r2, r2, #3
+	beqz	r3, byte_copy
+	addi	r4, #-4
+word_copy:
+	ld	r7, @r1+
+	addi	r3, #-1
+	st	r7, @+r4
+	bnez	r3, word_copy
+	beqz	r2, end_memcopy
+	addi	r4, #4
+byte_copy:
+	ldb	r7, @r1
+	addi	r1, #1
+	addi	r2, #-1
+	stb	r7, @r4
+	addi	r4, #1
+	bnez	r2, byte_copy
+end_memcopy:
+	jmp	r14
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+	.end
diff --git a/arch/m32r/lib/memset.S b/arch/m32r/lib/memset.S
new file mode 100644
index 0000000..6e26df1
--- /dev/null
+++ b/arch/m32r/lib/memset.S
@@ -0,0 +1,181 @@
+/*
+ *  linux/arch/m32r/lib/memset.S
+ *
+ *  Copyright (C) 2001,2002  Hiroyuki Kondo, and Hirokazu Takata
+ *  Copyright (C) 2004  Hirokazu Takata
+ *
+ *  void *memset(void *dst, int val, int len);
+ *
+ *        dst: r0
+ *        val: r1
+ *        len: r2
+ *        ret: r0
+ *
+ */
+/* $Id$ */
+
+#include <linux/config.h>
+
+	.text
+	.global	memset
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+	.align 4
+memset:
+	mv      r4, r0		    ||	cmpz	r2
+	jc	r14
+	cmpui	r2, #16
+	bnc	qword_align_check
+	cmpui	r2, #4
+	bc	byte_set
+word_align_check:			/* len >= 4 */
+	and3	r3, r4, #3
+	beqz	r3, word_set
+	addi	r3, #-4
+	neg	r3, r3			/* r3 = -(r3 - 4) */
+align_word:
+	stb	r1, @r4		    ||	addi	r4, #1
+	addi	r2, #-1		    ||	addi	r3, #-1
+	bnez	r3, align_word
+	cmpui	r2, #4
+	bc	byte_set
+word_set:
+	and3	r1, r1, #0x00ff		/* r1: abababab <-- ??????ab */
+	sll3	r3, r1, #8
+	or	r1, r3		    ||	addi	r4, #-4
+	sll3	r3, r1, #16
+	or	r1, r3		    ||	addi	r2, #-4
+word_set_loop:
+	st	r1, @+r4	    ||	addi	r2, #-4
+	bgtz	r2, word_set_loop
+	bnez	r2, byte_set_wrap
+	st	r1, @+r4
+	jmp	r14
+
+qword_align_check:			/* len >= 16 */
+	and3	r3, r4, #15
+	bnez	r3, word_align_check
+qword_set:
+	and3	r1, r1, #0x00ff		/* r1: abababab <-- ??????ab */
+	sll3	r3, r1, #8
+	or	r1, r3		    ||	addi	r4, #-4
+	sll3	r3, r1, #16
+	or	r1, r3		    ||	ldi	r5, #16
+qword_set_loop:
+	ld	r3, @(4,r4)		/* cache line allocate */
+	st	r1, @+r4	    ||	addi	r2, #-16
+	st	r1, @+r4	    ||	cmpu	r2, r5
+	st	r1, @+r4
+	st	r1, @+r4
+	bnc	qword_set_loop	    ||  cmpz	r2
+	jc	r14
+set_remainder:
+	cmpui	r2, #4
+	bc	byte_set_wrap1
+	addi	r2, #-4
+	bra	word_set_loop
+
+byte_set_wrap:
+	addi	r2, #4
+	cmpz	r2
+	jc	r14
+byte_set_wrap1:
+	addi	r4, #4
+#if defined(CONFIG_ISA_M32R2)
+byte_set:
+	addi	r2, #-1		    ||	stb	r1, @r4+
+	bnez	r2, byte_set
+#elif defined(CONFIG_ISA_M32R)
+byte_set:
+	addi	r2, #-1		    ||	stb	r1, @r4
+	addi	r4, #1
+	bnez	r2, byte_set
+#else
+#error unknown isa configuration
+#endif
+end_memset:
+	jmp	r14
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+	.align 4
+memset:
+	mv      r4, r0
+	beqz	r2, end_memset
+	cmpui	r2, #16
+	bnc	qword_align_check
+	cmpui	r2, #4
+	bc	byte_set
+word_align_check:			/* len >= 4 */
+	and3	r3, r4, #3
+	beqz	r3, word_set
+	addi	r3, #-4
+	neg	r3, r3			/* r3 = -(r3 - 4) */
+align_word:
+	stb	r1, @r4
+	addi	r4, #1
+	addi	r2, #-1
+	addi	r3, #-1
+	bnez	r3, align_word
+	cmpui	r2, #4
+	bc	byte_set
+word_set:
+	and3	r1, r1, #0x00ff		/* r1: abababab <-- ??????ab */
+	sll3	r3, r1, #8
+	or	r1, r3
+	sll3	r3, r1, #16
+	or	r1, r3
+	addi	r2, #-4
+	addi	r4, #-4
+word_set_loop:
+	st	r1, @+r4
+	addi	r2, #-4
+	bgtz    r2, word_set_loop
+	bnez	r2, byte_set_wrap
+	st	r1, @+r4
+	jmp	r14
+
+qword_align_check:			/* len >= 16 */
+	and3	r3, r4, #15
+	bnez	r3, word_align_check
+qword_set:
+	and3	r1, r1, #0x00ff		/* r1: abababab <-- ??????ab */
+	sll3	r3, r1, #8
+	or	r1, r3
+	sll3	r3, r1, #16
+	or	r1, r3
+	addi	r4, #-4
+qword_set_loop:
+	ld	r3, @(4,r4)		/* cache line allocate */
+	addi	r2, #-16
+	st	r1, @+r4
+	st	r1, @+r4
+	cmpui	r2, #16
+	st	r1, @+r4
+	st	r1, @+r4
+	bnc	qword_set_loop
+	bnez	r2, set_remainder
+	jmp	r14
+set_remainder:
+	cmpui	r2, #4
+	bc	byte_set_wrap1
+	addi	r2, #-4
+	bra	word_set_loop
+
+byte_set_wrap:
+	addi	r2, #4
+	beqz	r2, end_memset
+byte_set_wrap1:
+	addi	r4, #4
+byte_set:
+	addi	r2, #-1
+	stb	r1, @r4
+	addi	r4, #1
+	bnez	r2, byte_set
+end_memset:
+	jmp	r14
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+	.end
diff --git a/arch/m32r/lib/putuser.S b/arch/m32r/lib/putuser.S
new file mode 100644
index 0000000..218154c
--- /dev/null
+++ b/arch/m32r/lib/putuser.S
@@ -0,0 +1,84 @@
+/*
+ * __put_user functions.
+ *
+ * (C) Copyright 1998 Linus Torvalds
+ * (C) Copyright 2001 Hirokazu Takata
+ *
+ * These functions have a non-standard call interface
+ * to make them more efficient.
+ */
+
+#include <linux/config.h>
+
+/*
+ * __put_user_X
+ *
+ * Inputs:	r0 contains the address
+ *		r1 contains the value
+ *
+ * Outputs:	r0 is error code (0 or -EFAULT)
+ *		r1 is corrupted (will contain "current_task").
+ *
+ * These functions should not modify any other registers,
+ * as they get called from within inline assembly.
+ */
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+	.text
+	.balign 4
+	.globl __put_user_1
+__put_user_1:
+1:	stb	r1, @r0		    ||	ldi	r0, #0
+	jmp	r14
+
+	.balign 4
+	.globl __put_user_2
+__put_user_2:
+2:	sth	r1, @r0		    ||	ldi	r0, #0
+	jmp	r14
+
+	.balign 4
+	.globl __put_user_4
+__put_user_4:
+3:	st	r1, @r0		    ||	ldi	r0, #0
+	jmp	r14
+
+bad_put_user:
+	ldi	r0, #-14	    ||	jmp	r14
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+	.text
+	.balign 4
+	.globl __put_user_1
+__put_user_1:
+1:	stb	r1, @r0
+	ldi	r0, #0
+	jmp	r14
+
+	.balign 4
+	.globl __put_user_2
+__put_user_2:
+2:	sth	r1, @r0
+	ldi	r0, #0
+	jmp	r14
+
+	.balign 4
+	.globl __put_user_4
+__put_user_4:
+3:	st	r1, @r0
+	ldi	r0, #0
+	jmp	r14
+
+bad_put_user:
+	ldi	r0, #-14
+	jmp	r14
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+.section __ex_table,"a"
+	.long 1b,bad_put_user
+	.long 2b,bad_put_user
+	.long 3b,bad_put_user
+.previous
diff --git a/arch/m32r/lib/strlen.S b/arch/m32r/lib/strlen.S
new file mode 100644
index 0000000..8d23cfb
--- /dev/null
+++ b/arch/m32r/lib/strlen.S
@@ -0,0 +1,120 @@
+/*
+ *  linux/arch/m32r/strlen.S --  strlen code.
+ *
+ *  Copyright (C) 2001  Hirokazu Takata
+ *
+ *  size_t strlen(const char *s);
+ *
+ */
+/* $Id$ */
+
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+	.text
+ENTRY(strlen)
+	mv	r6, r0		    ||	ldi	r2, #0
+	and3	r0, r0, #3
+	bnez	r0, strlen_byte
+;
+strlen_word:
+	ld	r0, @r6+
+;
+	seth	r5, #high(0x01010101)
+	or3	r5, r5, #low(0x01010101)
+	sll3	r7, r5, #7
+strlen_word_loop:
+	ld	r1, @r6+	    ||	not	r4, r0
+	sub	r0, r5		    ||	and	r4, r7
+	and	r4, r0
+	bnez	r4, strlen_last_bytes
+	ld	r0, @r6+	    ||	not	r4, r1
+	sub	r1, r5		    ||	and	r4, r7
+	and	r4, r1		    ||	addi	r2, #4
+	bnez	r4, strlen_last_bytes
+	addi	r2, #4		    ||	bra.s	strlen_word_loop
+
+	; NOTE: If a null char. exists, return 0.
+	; if ((x - 0x01010101) & ~x & 0x80808080)
+	;     return 0;
+;
+strlen_byte:
+	ldb	r1, @r6		    ||	addi	r6, #1
+	beqz	r1, strlen_exit
+	addi	r2, #1		    ||	bra.s	strlen_byte
+;
+strlen_last_bytes:
+	ldi	r0, #4		    ||	addi	r6, #-8
+;
+strlen_byte_loop:
+	ldb	r1, @r6		    ||	addi	r6, #1
+	addi	r0, #-1		    ||  cmpz	r1
+	bc.s	strlen_exit	    ||  cmpz	r0
+	addi	r2, #1		    ||	bnc.s	strlen_byte_loop
+;
+strlen_exit:
+	mv	r0, r2		    ||	jmp	r14
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+	.text
+ENTRY(strlen)
+	mv	r6, r0
+	ldi	r2, #0
+	and3	r0, r0, #3
+	bnez	r0, strlen_byte
+;
+strlen_word:
+	ld	r0, @r6+
+;
+	seth	r5, #high(0x01010101)
+	or3	r5, r5, #low(0x01010101)
+	sll3	r7, r5, #7
+strlen_word_loop:
+	ld	r1, @r6+
+	not	r4, r0		; NOTE: If a null char. exists, return 0.
+	sub	r0, r5		; if ((x - 0x01010101) & ~x & 0x80808080)
+	and	r4, r7		;     return 0;
+	and	r4, r0
+	bnez	r4, strlen_last_bytes
+	addi	r2, #4
+;
+	ld	r0, @r6+
+	not	r4, r1		; NOTE: If a null char. exists, return 0.
+	sub	r1, r5		; if ((x - 0x01010101) & ~x & 0x80808080)
+	and	r4, r7		;     return 0;
+	and	r4, r1
+	bnez	r4, strlen_last_bytes
+	addi	r2, #4
+	bra	strlen_word_loop
+;
+strlen_byte:
+	ldb	r1, @r6
+	addi	r6, #1
+	beqz	r1, strlen_exit
+	addi	r2, #1
+	bra	strlen_byte
+;
+strlen_last_bytes:
+	ldi	r0, #4
+	addi	r6, #-8
+;
+strlen_byte_loop:
+	ldb	r1, @r6
+	addi	r6, #1
+	addi	r0, #-1
+	beqz	r1, strlen_exit
+	addi	r2, #1
+	bnez	r0, strlen_byte_loop
+;
+strlen_exit:
+	mv	r0, r2
+	jmp	r14
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+	.end
diff --git a/arch/m32r/lib/usercopy.c b/arch/m32r/lib/usercopy.c
new file mode 100644
index 0000000..6c6855f
--- /dev/null
+++ b/arch/m32r/lib/usercopy.c
@@ -0,0 +1,391 @@
+/*
+ * User address space access functions.
+ * The non inlined parts of asm-m32r/uaccess.h are here.
+ *
+ * Copyright 1997 Andi Kleen <ak@muc.de>
+ * Copyright 1997 Linus Torvalds
+ * Copyright 2001, 2002, 2004 Hirokazu Takata
+ */
+#include <linux/config.h>
+#include <linux/prefetch.h>
+#include <linux/string.h>
+#include <linux/thread_info.h>
+#include <asm/uaccess.h>
+
+unsigned long
+__generic_copy_to_user(void *to, const void *from, unsigned long n)
+{
+	prefetch(from);
+	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)
+{
+	prefetchw(to);
+	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.
+ */
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+#define __do_strncpy_from_user(dst,src,count,res)			\
+do {									\
+	int __d0, __d1, __d2;						\
+	__asm__ __volatile__(						\
+		"	beqz	%1, 2f\n"				\
+		"	.fillinsn\n"					\
+		"0:	ldb	r14, @%3    ||	addi	%3, #1\n"	\
+		"	stb	r14, @%4    ||	addi	%4, #1\n"	\
+		"	beqz	r14, 1f\n"				\
+		"	addi	%1, #-1\n"				\
+		"	bnez	%1, 0b\n"				\
+		"	.fillinsn\n"					\
+		"1:	sub	%0, %1\n"				\
+		"	.fillinsn\n"					\
+		"2:\n"							\
+		".section .fixup,\"ax\"\n"				\
+		"	.balign 4\n"					\
+		"3:	seth	r14, #high(2b)\n"			\
+		"	or3	r14, r14, #low(2b)\n"			\
+		"	jmp	r14	    ||	ldi	%0, #%5\n"	\
+		".previous\n"						\
+		".section __ex_table,\"a\"\n"				\
+		"	.balign 4\n"					\
+		"	.long 0b,3b\n"					\
+		".previous"						\
+		: "=r"(res), "=r"(count), "=&r" (__d0), "=&r" (__d1),	\
+		  "=&r" (__d2)						\
+		: "i"(-EFAULT), "0"(count), "1"(count), "3"(src), 	\
+		  "4"(dst)						\
+		: "r14", "cbit", "memory");				\
+} while (0)
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+#define __do_strncpy_from_user(dst,src,count,res)			\
+do {									\
+	int __d0, __d1, __d2;						\
+	__asm__ __volatile__(						\
+		"	beqz	%1, 2f\n"				\
+		"	.fillinsn\n"					\
+		"0:	ldb	r14, @%3\n"				\
+		"	stb	r14, @%4\n"				\
+		"	addi	%3, #1\n"				\
+		"	addi	%4, #1\n"				\
+		"	beqz	r14, 1f\n"				\
+		"	addi	%1, #-1\n"				\
+		"	bnez	%1, 0b\n"				\
+		"	.fillinsn\n"					\
+		"1:	sub	%0, %1\n"				\
+		"	.fillinsn\n"					\
+		"2:\n"							\
+		".section .fixup,\"ax\"\n"				\
+		"	.balign 4\n"					\
+		"3:	ldi	%0, #%5\n"				\
+		"	seth	r14, #high(2b)\n"			\
+		"	or3	r14, r14, #low(2b)\n"			\
+		"	jmp	r14\n"					\
+		".previous\n"						\
+		".section __ex_table,\"a\"\n"				\
+		"	.balign 4\n"					\
+		"	.long 0b,3b\n"					\
+		".previous"						\
+		: "=r"(res), "=r"(count), "=&r" (__d0), "=&r" (__d1),	\
+		  "=&r" (__d2)						\
+		: "i"(-EFAULT), "0"(count), "1"(count), "3"(src),	\
+		  "4"(dst)						\
+		: "r14", "cbit", "memory");				\
+} while (0)
+
+#endif /* CONFIG_ISA_DUAL_ISSUE */
+
+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;
+}
+
+
+/*
+ * Zero Userspace
+ */
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+#define __do_clear_user(addr,size)					\
+do {									\
+	int __dst, __c;							\
+  	__asm__ __volatile__(						\
+		"	beqz	%1, 9f\n"				\
+		"	and3	r14, %0, #3\n"				\
+		"	bnez	r14, 2f\n"				\
+		"	and3	r14, %1, #3\n"				\
+		"	bnez	r14, 2f\n"				\
+		"	and3	%1, %1, #3\n"				\
+		"	beqz	%2, 2f\n"				\
+		"	addi	%0, #-4\n"				\
+		"	.fillinsn\n"					\
+		"0:	; word clear \n"				\
+		"	st	%6, @+%0    ||	addi	%2, #-1\n"	\
+		"	bnez	%2, 0b\n"				\
+		"	beqz	%1, 9f\n"				\
+		"	.fillinsn\n"					\
+		"2:	; byte clear \n"				\
+		"	stb	%6, @%0	    ||	addi	%1, #-1\n"	\
+		"	addi	%0, #1\n"				\
+		"	bnez	%1, 2b\n"				\
+		"	.fillinsn\n"					\
+		"9:\n"							\
+		".section .fixup,\"ax\"\n"				\
+		"	.balign 4\n"					\
+		"4:	slli	%2, #2\n"				\
+		"	seth	r14, #high(9b)\n"			\
+		"	or3	r14, r14, #low(9b)\n"			\
+		"	jmp	r14	    ||	add	%1, %2\n"	\
+		".previous\n"						\
+		".section __ex_table,\"a\"\n"				\
+		"	.balign 4\n"					\
+		"	.long 0b,4b\n"					\
+		"	.long 2b,9b\n"					\
+		".previous\n"						\
+		: "=&r"(__dst), "=&r"(size), "=&r"(__c)			\
+		: "0"(addr), "1"(size), "2"(size / 4), "r"(0)		\
+		: "r14", "cbit", "memory");				\
+} while (0)
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+#define __do_clear_user(addr,size)					\
+do {									\
+	int __dst, __c;							\
+  	__asm__ __volatile__(						\
+		"	beqz	%1, 9f\n"				\
+		"	and3	r14, %0, #3\n"				\
+		"	bnez	r14, 2f\n"				\
+		"	and3	r14, %1, #3\n"				\
+		"	bnez	r14, 2f\n"				\
+		"	and3	%1, %1, #3\n"				\
+		"	beqz	%2, 2f\n"				\
+		"	addi	%0, #-4\n"				\
+		"	.fillinsn\n"					\
+		"0:	st	%6, @+%0	; word clear \n"	\
+		"	addi	%2, #-1\n"				\
+		"	bnez	%2, 0b\n"				\
+		"	beqz	%1, 9f\n"				\
+		"	.fillinsn\n"					\
+		"2:	stb	%6, @%0		; byte clear \n"	\
+		"	addi	%1, #-1\n"				\
+		"	addi	%0, #1\n"				\
+		"	bnez	%1, 2b\n"				\
+		"	.fillinsn\n"					\
+		"9:\n"							\
+		".section .fixup,\"ax\"\n"				\
+		"	.balign 4\n"					\
+		"4:	slli	%2, #2\n"				\
+		"	add	%1, %2\n"				\
+		"	seth	r14, #high(9b)\n"			\
+		"	or3	r14, r14, #low(9b)\n"			\
+		"	jmp	r14\n"					\
+		".previous\n"						\
+		".section __ex_table,\"a\"\n"				\
+		"	.balign 4\n"					\
+		"	.long 0b,4b\n"					\
+		"	.long 2b,9b\n"					\
+		".previous\n"						\
+		: "=&r"(__dst), "=&r"(size), "=&r"(__c)			\
+		: "0"(addr), "1"(size), "2"(size / 4), "r"(0)		\
+		: "r14", "cbit", "memory");				\
+} while (0)
+
+#endif /* not CONFIG_ISA_DUAL_ISSUE */
+
+unsigned long
+clear_user(void *to, unsigned long n)
+{
+	if (access_ok(VERIFY_WRITE, to, n))
+		__do_clear_user(to, n);
+	return n;
+}
+
+unsigned long
+__clear_user(void *to, unsigned long 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
+ */
+
+#ifdef CONFIG_ISA_DUAL_ISSUE
+
+long strnlen_user(const char *s, long n)
+{
+	unsigned long mask = -__addr_ok(s);
+	unsigned long res;
+
+	__asm__ __volatile__(
+		"	and	%0, %5	    ||	mv	r1, %1\n"
+		"	beqz	%0, strnlen_exit\n"
+		"	and3	r0, %1, #3\n"
+		"	bnez	r0, strnlen_byte_loop\n"
+		"	cmpui	%0, #4\n"
+		"	bc	strnlen_byte_loop\n"
+		"strnlen_word_loop:\n"
+		"0:	ld	r0, @%1+\n"
+		"	pcmpbz	r0\n"
+		"	bc	strnlen_last_bytes_fixup\n"
+		"	addi	%0, #-4\n"
+		"	beqz	%0, strnlen_exit\n"
+		"	bgtz	%0, strnlen_word_loop\n"
+		"strnlen_last_bytes:\n"
+		"	mv	%0, %4\n"
+		"strnlen_last_bytes_fixup:\n"
+		"	addi	%1, #-4\n"
+		"strnlen_byte_loop:\n"
+		"1:	ldb	r0, @%1	    ||	addi	%0, #-1\n"
+		"	beqz	r0, strnlen_exit\n"
+		"	addi	%1, #1\n"
+		"	bnez	%0, strnlen_byte_loop\n"
+		"strnlen_exit:\n"
+		"	sub	%1, r1\n"
+		"	add3	%0, %1, #1\n"
+		"	.fillinsn\n"
+		"9:\n"
+		".section .fixup,\"ax\"\n"
+		"	.balign 4\n"
+		"4:	addi	%1, #-4\n"
+		"	.fillinsn\n"
+		"5:	seth	r1, #high(9b)\n"
+		"	or3	r1, r1, #low(9b)\n"
+		"	jmp	r1	    ||	ldi	%0, #0\n"
+		".previous\n"
+		".section __ex_table,\"a\"\n"
+		"	.balign 4\n"
+		"	.long 0b,4b\n"
+		"	.long 1b,5b\n"
+		".previous"
+		: "=&r" (res), "=r" (s)
+		: "0" (n), "1" (s), "r" (n & 3), "r" (mask), "r"(0x01010101)
+		: "r0", "r1", "cbit");
+
+	/* NOTE: strnlen_user() algorism:
+	 * {
+	 *   char *p;
+	 *   for (p = s; n-- && *p != '\0'; ++p)
+	 *     ;
+	 *   return p - s + 1;
+	 * }
+	 */
+
+	/* NOTE: If a null char. exists, return 0.
+	 * if ((x - 0x01010101) & ~x & 0x80808080)\n"
+	 *   return 0;\n"
+	 */
+
+	return res & mask;
+}
+
+#else /* not CONFIG_ISA_DUAL_ISSUE */
+
+long strnlen_user(const char *s, long n)
+{
+	unsigned long mask = -__addr_ok(s);
+	unsigned long res;
+
+	__asm__ __volatile__(
+		"	and	%0, %5\n"
+		"	mv	r1, %1\n"
+		"	beqz	%0, strnlen_exit\n"
+		"	and3	r0, %1, #3\n"
+		"	bnez	r0, strnlen_byte_loop\n"
+		"	cmpui	%0, #4\n"
+		"	bc	strnlen_byte_loop\n"
+		"	sll3	r3, %6, #7\n"
+		"strnlen_word_loop:\n"
+		"0:	ld	r0, @%1+\n"
+		"	not	r2, r0\n"
+		"	sub	r0, %6\n"
+		"	and	r2, r3\n"
+		"	and	r2, r0\n"
+		"	bnez	r2, strnlen_last_bytes_fixup\n"
+		"	addi	%0, #-4\n"
+		"	beqz	%0, strnlen_exit\n"
+		"	bgtz	%0, strnlen_word_loop\n"
+		"strnlen_last_bytes:\n"
+		"	mv	%0, %4\n"
+		"strnlen_last_bytes_fixup:\n"
+		"	addi	%1, #-4\n"
+		"strnlen_byte_loop:\n"
+		"1:	ldb	r0, @%1\n"
+		"	addi	%0, #-1\n"
+		"	beqz	r0, strnlen_exit\n"
+		"	addi	%1, #1\n"
+		"	bnez	%0, strnlen_byte_loop\n"
+		"strnlen_exit:\n"
+		"	sub	%1, r1\n"
+		"	add3	%0, %1, #1\n"
+		"	.fillinsn\n"
+		"9:\n"
+		".section .fixup,\"ax\"\n"
+		"	.balign 4\n"
+		"4:	addi	%1, #-4\n"
+		"	.fillinsn\n"
+		"5:	ldi	%0, #0\n"
+		"	seth	r1, #high(9b)\n"
+		"	or3	r1, r1, #low(9b)\n"
+		"	jmp	r1\n"
+		".previous\n"
+		".section __ex_table,\"a\"\n"
+		"	.balign 4\n"
+		"	.long 0b,4b\n"
+		"	.long 1b,5b\n"
+		".previous"
+		: "=&r" (res), "=r" (s)
+		: "0" (n), "1" (s), "r" (n & 3), "r" (mask), "r"(0x01010101)
+		: "r0", "r1", "r2", "r3", "cbit");
+
+	/* NOTE: strnlen_user() algorism:
+	 * {
+	 *   char *p;
+	 *   for (p = s; n-- && *p != '\0'; ++p)
+	 *     ;
+	 *   return p - s + 1;
+	 * }
+	 */
+
+	/* NOTE: If a null char. exists, return 0.
+	 * if ((x - 0x01010101) & ~x & 0x80808080)\n"
+	 *   return 0;\n"
+	 */
+
+	return res & mask;
+}
+
+#endif /* CONFIG_ISA_DUAL_ISSUE */
+