diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/m32r/lib |
Linux-2.6.12-rc2v2.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!
Diffstat (limited to 'arch/m32r/lib')
-rw-r--r-- | arch/m32r/lib/Makefile | 7 | ||||
-rw-r--r-- | arch/m32r/lib/ashxdi3.S | 297 | ||||
-rw-r--r-- | arch/m32r/lib/checksum.S | 322 | ||||
-rw-r--r-- | arch/m32r/lib/csum_partial_copy.c | 60 | ||||
-rw-r--r-- | arch/m32r/lib/delay.c | 126 | ||||
-rw-r--r-- | arch/m32r/lib/getuser.S | 88 | ||||
-rw-r--r-- | arch/m32r/lib/memcpy.S | 95 | ||||
-rw-r--r-- | arch/m32r/lib/memset.S | 181 | ||||
-rw-r--r-- | arch/m32r/lib/putuser.S | 84 | ||||
-rw-r--r-- | arch/m32r/lib/strlen.S | 120 | ||||
-rw-r--r-- | arch/m32r/lib/usercopy.c | 391 |
11 files changed, 1771 insertions, 0 deletions
diff --git a/arch/m32r/lib/Makefile b/arch/m32r/lib/Makefile new file mode 100644 index 00000000000..e632d10c7d7 --- /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 00000000000..78effca9d97 --- /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 00000000000..f6fc1bdb87e --- /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 00000000000..c871b4606b0 --- /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 00000000000..fb29632c7ea --- /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 00000000000..58a0db055c5 --- /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 00000000000..800898a2d2e --- /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 00000000000..6e26df120ac --- /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 00000000000..218154cc389 --- /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 + |