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!
This commit is contained in:
7
arch/m32r/lib/Makefile
Normal file
7
arch/m32r/lib/Makefile
Normal file
@@ -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
|
||||
|
297
arch/m32r/lib/ashxdi3.S
Normal file
297
arch/m32r/lib/ashxdi3.S
Normal file
@@ -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
|
||||
|
322
arch/m32r/lib/checksum.S
Normal file
322
arch/m32r/lib/checksum.S
Normal file
@@ -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
|
||||
|
60
arch/m32r/lib/csum_partial_copy.c
Normal file
60
arch/m32r/lib/csum_partial_copy.c
Normal file
@@ -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);
|
126
arch/m32r/lib/delay.c
Normal file
126
arch/m32r/lib/delay.c
Normal file
@@ -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) */
|
||||
}
|
88
arch/m32r/lib/getuser.S
Normal file
88
arch/m32r/lib/getuser.S
Normal file
@@ -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
|
95
arch/m32r/lib/memcpy.S
Normal file
95
arch/m32r/lib/memcpy.S
Normal file
@@ -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
|
181
arch/m32r/lib/memset.S
Normal file
181
arch/m32r/lib/memset.S
Normal file
@@ -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
|
84
arch/m32r/lib/putuser.S
Normal file
84
arch/m32r/lib/putuser.S
Normal file
@@ -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
|
120
arch/m32r/lib/strlen.S
Normal file
120
arch/m32r/lib/strlen.S
Normal file
@@ -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
|
391
arch/m32r/lib/usercopy.c
Normal file
391
arch/m32r/lib/usercopy.c
Normal file
@@ -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 */
|
||||
|
Reference in New Issue
Block a user