aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mn10300/lib
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2008-02-08 07:19:31 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-08 12:22:30 -0500
commitb920de1b77b72ca9432ac3f97edb26541e65e5dd (patch)
tree40fa9be1470e929c47927dea7eddf184c0204229 /arch/mn10300/lib
parentef3d534754f31fed9c3b976fee1ece1b3bc38282 (diff)
mn10300: add the MN10300/AM33 architecture to the kernel
Add architecture support for the MN10300/AM33 CPUs produced by MEI to the kernel. This patch also adds board support for the ASB2303 with the ASB2308 daughter board, and the ASB2305. The only processor supported is the MN103E010, which is an AM33v2 core plus on-chip devices. [akpm@linux-foundation.org: nuke cvs control strings] Signed-off-by: Masakazu Urade <urade.masakazu@jp.panasonic.com> Signed-off-by: Koichi Yasutake <yasutake.koichi@jp.panasonic.com> Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/mn10300/lib')
-rw-r--r--arch/mn10300/lib/Makefile7
-rw-r--r--arch/mn10300/lib/__ashldi3.S51
-rw-r--r--arch/mn10300/lib/__ashrdi3.S52
-rw-r--r--arch/mn10300/lib/__lshrdi3.S52
-rw-r--r--arch/mn10300/lib/ashrdi3.c61
-rw-r--r--arch/mn10300/lib/bitops.c51
-rw-r--r--arch/mn10300/lib/checksum.c99
-rw-r--r--arch/mn10300/lib/delay.c50
-rw-r--r--arch/mn10300/lib/do_csum.S162
-rw-r--r--arch/mn10300/lib/internal.h15
-rw-r--r--arch/mn10300/lib/lshrdi3.c60
-rw-r--r--arch/mn10300/lib/memcpy.S135
-rw-r--r--arch/mn10300/lib/memmove.S160
-rw-r--r--arch/mn10300/lib/memset.S121
-rw-r--r--arch/mn10300/lib/negdi2.c57
-rw-r--r--arch/mn10300/lib/usercopy.c166
16 files changed, 1299 insertions, 0 deletions
diff --git a/arch/mn10300/lib/Makefile b/arch/mn10300/lib/Makefile
new file mode 100644
index 000000000000..fdfa9ec5b5bb
--- /dev/null
+++ b/arch/mn10300/lib/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for the MN10300-specific library files..
3#
4
5lib-y = delay.o usercopy.o checksum.o bitops.o memcpy.o memmove.o memset.o
6lib-y += do_csum.o
7lib-y += __ashldi3.o __ashrdi3.o __lshrdi3.o negdi2.o
diff --git a/arch/mn10300/lib/__ashldi3.S b/arch/mn10300/lib/__ashldi3.S
new file mode 100644
index 000000000000..a51a9506f00c
--- /dev/null
+++ b/arch/mn10300/lib/__ashldi3.S
@@ -0,0 +1,51 @@
1/* MN10300 64-bit arithmetic left shift
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <asm/cache.h>
12
13 .text
14 .balign L1_CACHE_BYTES
15
16###############################################################################
17#
18# unsigned long long __ashldi3(unsigned long long value [D1:D0],
19# unsigned by [(12,SP)])
20#
21###############################################################################
22 .globl __ashldi3
23 .type __ashldi3,@function
24__ashldi3:
25 mov (12,sp),a0
26 and +63,a0
27 beq __ashldi3_zero
28
29 cmp +31,a0
30 bhi __ashldi3_32plus
31
32 # the count is in the range 1-31
33 asl a0,d1
34
35 mov +32,a1
36 sub a0,a1,a1 # a1 = 32 - count
37 lsr a1,d0,a1 # get overflow from LSW -> MSW
38
39 or_asl a1,d1,a0,d0 # insert overflow into MSW and
40 # shift the LSW
41 rets
42
43 .balign L1_CACHE_BYTES
44 # the count is in the range 32-63
45__ashldi3_32plus:
46 asl a0,d0,d1
47 clr d0
48__ashldi3_zero:
49 rets
50
51 .size __ashldi3, .-__ashldi3
diff --git a/arch/mn10300/lib/__ashrdi3.S b/arch/mn10300/lib/__ashrdi3.S
new file mode 100644
index 000000000000..6f42382728cb
--- /dev/null
+++ b/arch/mn10300/lib/__ashrdi3.S
@@ -0,0 +1,52 @@
1/* MN10300 64-bit arithmetic right shift
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <asm/cache.h>
12
13 .text
14 .balign L1_CACHE_BYTES
15
16###############################################################################
17#
18# unsigned long long __ashrdi3(unsigned long long value [D1:D0],
19# unsigned by [(12,SP)])
20#
21###############################################################################
22 .globl __ashrdi3
23 .type __ashrdi3,@function
24__ashrdi3:
25 mov (12,sp),a0
26 and +63,a0
27 beq __ashrdi3_zero
28
29 cmp +31,a0
30 bhi __ashrdi3_32plus
31
32 # the count is in the range 1-31
33 lsr a0,d0
34
35 mov +32,a1
36 sub a0,a1,a1 # a1 = 32 - count
37 asl a1,d1,a1 # get underflow from MSW -> LSW
38
39 or_asr a1,d0,a0,d1 # insert underflow into LSW and
40 # shift the MSW
41 rets
42
43 .balign L1_CACHE_BYTES
44 # the count is in the range 32-63
45__ashrdi3_32plus:
46 asr a0,d1,d0
47 ext d0 # sign-extend result through MDR
48 mov mdr,d1
49__ashrdi3_zero:
50 rets
51
52 .size __ashrdi3, .-__ashrdi3
diff --git a/arch/mn10300/lib/__lshrdi3.S b/arch/mn10300/lib/__lshrdi3.S
new file mode 100644
index 000000000000..a686aef31e90
--- /dev/null
+++ b/arch/mn10300/lib/__lshrdi3.S
@@ -0,0 +1,52 @@
1/* MN10300 64-bit logical right shift
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#include <asm/cache.h>
13
14 .text
15 .balign L1_CACHE_BYTES
16
17###############################################################################
18#
19# unsigned long long __lshrdi3(unsigned long long value [D1:D0],
20# unsigned by [(12,SP)])
21#
22###############################################################################
23 .globl __lshrdi3
24 .type __lshrdi3,@function
25__lshrdi3:
26 mov (12,sp),a0
27 and +63,a0
28 beq __lshrdi3_zero
29
30 cmp +31,a0
31 bhi __lshrdi3_32plus
32
33 # the count is in the range 1-31
34 lsr a0,d0
35
36 mov +32,a1
37 sub a0,a1,a1 # a1 = 32 - count
38 asl a1,d1,a1 # get underflow from MSW -> LSW
39
40 or_lsr a1,d0,a0,d1 # insert underflow into LSW and
41 # shift the MSW
42 rets
43
44 .balign L1_CACHE_BYTES
45 # the count is in the range 32-63
46__lshrdi3_32plus:
47 lsr a0,d1,d0
48 clr d1
49__lshrdi3_zero:
50 rets
51
52 .size __lshrdi3, .-__lshrdi3
diff --git a/arch/mn10300/lib/ashrdi3.c b/arch/mn10300/lib/ashrdi3.c
new file mode 100644
index 000000000000..c54f61ddf0b5
--- /dev/null
+++ b/arch/mn10300/lib/ashrdi3.c
@@ -0,0 +1,61 @@
1/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
2/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public Licence as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public Licence for more details.
15
16You should have received a copy of the GNU General Public Licence
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21#define BITS_PER_UNIT 8
22
23typedef int SItype __attribute__((mode(SI)));
24typedef unsigned int USItype __attribute__((mode(SI)));
25typedef int DItype __attribute__((mode(DI)));
26typedef int word_type __attribute__((mode(__word__)));
27
28struct DIstruct {
29 SItype low;
30 SItype high;
31};
32
33union DIunion {
34 struct DIstruct s;
35 DItype ll;
36};
37
38DItype __ashrdi3(DItype u, word_type b)
39{
40 union DIunion w;
41 union DIunion uu;
42 word_type bm;
43
44 if (b == 0)
45 return u;
46
47 uu.ll = u;
48
49 bm = (sizeof(SItype) * BITS_PER_UNIT) - b;
50 if (bm <= 0) {
51 /* w.s.high = 1..1 or 0..0 */
52 w.s.high = uu.s.high >> (sizeof(SItype) * BITS_PER_UNIT - 1);
53 w.s.low = uu.s.high >> -bm;
54 } else {
55 USItype carries = (USItype)uu.s.high << bm;
56 w.s.high = uu.s.high >> b;
57 w.s.low = ((USItype)uu.s.low >> b) | carries;
58 }
59
60 return w.ll;
61}
diff --git a/arch/mn10300/lib/bitops.c b/arch/mn10300/lib/bitops.c
new file mode 100644
index 000000000000..440a7dcbf87b
--- /dev/null
+++ b/arch/mn10300/lib/bitops.c
@@ -0,0 +1,51 @@
1/* MN10300 Non-trivial bit operations
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/module.h>
12#include <asm/bitops.h>
13#include <asm/system.h>
14
15/*
16 * try flipping a bit using BSET and BCLR
17 */
18void change_bit(int nr, volatile void *addr)
19{
20 if (test_bit(nr, addr))
21 goto try_clear_bit;
22
23try_set_bit:
24 if (!test_and_set_bit(nr, addr))
25 return;
26
27try_clear_bit:
28 if (test_and_clear_bit(nr, addr))
29 return;
30
31 goto try_set_bit;
32}
33
34/*
35 * try flipping a bit using BSET and BCLR and returning the old value
36 */
37int test_and_change_bit(int nr, volatile void *addr)
38{
39 if (test_bit(nr, addr))
40 goto try_clear_bit;
41
42try_set_bit:
43 if (!test_and_set_bit(nr, addr))
44 return 0;
45
46try_clear_bit:
47 if (test_and_clear_bit(nr, addr))
48 return 1;
49
50 goto try_set_bit;
51}
diff --git a/arch/mn10300/lib/checksum.c b/arch/mn10300/lib/checksum.c
new file mode 100644
index 000000000000..274f29ec33c1
--- /dev/null
+++ b/arch/mn10300/lib/checksum.c
@@ -0,0 +1,99 @@
1/* MN10300 Optimised checksumming wrappers
2 *
3 * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public Licence
9 * as published by the Free Software Foundation; either version
10 * 2 of the Licence, or (at your option) any later version.
11 */
12#include <linux/module.h>
13#include <linux/errno.h>
14#include <asm/byteorder.h>
15#include <asm/uaccess.h>
16#include <asm/checksum.h>
17#include "internal.h"
18
19static inline unsigned short from32to16(__wsum sum)
20{
21 asm(" add %1,%0 \n"
22 " addc 0xffff,%0 \n"
23 : "=r" (sum)
24 : "r" (sum << 16), "0" (sum & 0xffff0000)
25 );
26 return sum >> 16;
27}
28
29__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
30{
31 return ~do_csum(iph, ihl * 4);
32}
33EXPORT_SYMBOL(ip_fast_csum);
34
35__wsum csum_partial(const void *buff, int len, __wsum sum)
36{
37 __wsum result;
38
39 result = do_csum(buff, len);
40 result += sum;
41 if (sum > result)
42 result++;
43 return result;
44}
45EXPORT_SYMBOL(csum_partial);
46
47__sum16 ip_compute_csum(const void *buff, int len)
48{
49 return ~from32to16(do_csum(buff, len));
50}
51EXPORT_SYMBOL(ip_compute_csum);
52
53__wsum csum_partial_copy(const void *src, void *dst, int len, __wsum sum)
54{
55 copy_from_user(dst, src, len);
56 return csum_partial(dst, len, sum);
57}
58EXPORT_SYMBOL(csum_partial_copy);
59
60__wsum csum_partial_copy_nocheck(const void *src, void *dst,
61 int len, __wsum sum)
62{
63 sum = csum_partial(src, len, sum);
64 memcpy(dst, src, len);
65 return sum;
66}
67EXPORT_SYMBOL(csum_partial_copy_nocheck);
68
69__wsum csum_partial_copy_from_user(const void *src, void *dst,
70 int len, __wsum sum,
71 int *err_ptr)
72{
73 int missing;
74
75 missing = copy_from_user(dst, src, len);
76 if (missing) {
77 memset(dst + len - missing, 0, missing);
78 *err_ptr = -EFAULT;
79 }
80
81 return csum_partial(dst, len, sum);
82}
83EXPORT_SYMBOL(csum_partial_copy_from_user);
84
85__wsum csum_and_copy_to_user(const void *src, void *dst,
86 int len, __wsum sum,
87 int *err_ptr)
88{
89 int missing;
90
91 missing = copy_to_user(dst, src, len);
92 if (missing) {
93 memset(dst + len - missing, 0, missing);
94 *err_ptr = -EFAULT;
95 }
96
97 return csum_partial(src, len, sum);
98}
99EXPORT_SYMBOL(csum_and_copy_to_user);
diff --git a/arch/mn10300/lib/delay.c b/arch/mn10300/lib/delay.c
new file mode 100644
index 000000000000..cce66bc0822d
--- /dev/null
+++ b/arch/mn10300/lib/delay.c
@@ -0,0 +1,50 @@
1/* MN10300 Short delay interpolation routines
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <linux/module.h>
12#include <linux/sched.h>
13#include <linux/delay.h>
14#include <asm/div64.h>
15
16/*
17 * basic delay loop
18 */
19void __delay(unsigned long loops)
20{
21 int d0;
22
23 asm volatile(
24 " bra 1f \n"
25 " .align 4 \n"
26 "1: bra 2f \n"
27 " .align 4 \n"
28 "2: add -1,%0 \n"
29 " bne 2b \n"
30 : "=&d" (d0)
31 : "0" (loops));
32}
33EXPORT_SYMBOL(__delay);
34
35/*
36 * handle a delay specified in terms of microseconds
37 */
38void __udelay(unsigned long usecs)
39{
40 signed long ioclk, stop;
41
42 /* usecs * CLK / 1E6 */
43 stop = __muldiv64u(usecs, MN10300_TSCCLK, 1000000);
44 stop = TMTSCBC - stop;
45
46 do {
47 ioclk = TMTSCBC;
48 } while (stop < ioclk);
49}
50EXPORT_SYMBOL(__udelay);
diff --git a/arch/mn10300/lib/do_csum.S b/arch/mn10300/lib/do_csum.S
new file mode 100644
index 000000000000..e138994e1667
--- /dev/null
+++ b/arch/mn10300/lib/do_csum.S
@@ -0,0 +1,162 @@
1/* Optimised simple memory checksum
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <asm/cache.h>
12
13 .section .text
14 .balign L1_CACHE_BYTES
15
16###############################################################################
17#
18# unsigned int do_csum(const unsigned char *buff, size_t len)
19#
20###############################################################################
21 .globl do_csum
22 .type do_csum,@function
23do_csum:
24 movm [d2,d3],(sp)
25 mov d0,(12,sp)
26 mov d1,(16,sp)
27 mov d1,d2 # count
28 mov d0,a0 # buff
29 clr d1 # accumulator
30
31 cmp +0,d2
32 beq do_csum_done # return if zero-length buffer
33
34 # 4-byte align the buffer pointer
35 btst +3,a0
36 beq do_csum_now_4b_aligned
37
38 btst +1,a0
39 beq do_csum_addr_not_odd
40 movbu (a0),d0
41 inc a0
42 asl +8,d0
43 add d0,d1
44 addc +0,d1
45 add -1,d2
46do_csum_addr_not_odd:
47
48 cmp +2,d2
49 bcs do_csum_fewer_than_4
50 btst +2,a0
51 beq do_csum_now_4b_aligned
52 movhu (a0+),d0
53 add d0,d1
54 addc +0,d1
55 add -2,d2
56 cmp +4,d2
57 bcs do_csum_fewer_than_4
58
59do_csum_now_4b_aligned:
60 # we want to checksum as much as we can in chunks of 32 bytes
61 cmp +31,d2
62 bls do_csum_remainder # 4-byte aligned remainder
63
64 add -32,d2
65 mov +32,d3
66
67do_csum_loop:
68 mov (a0+),d0
69 add d0,d1
70 mov (a0+),e0
71 addc e0,d1
72 mov (a0+),e1
73 addc e1,d1
74 mov (a0+),e3
75 addc e3,d1
76 mov (a0+),d0
77 addc d0,d1
78 mov (a0+),e0
79 addc e0,d1
80 mov (a0+),e1
81 addc e1,d1
82 mov (a0+),e3
83 addc e3,d1
84 addc +0,d1
85
86 sub d3,d2
87 bcc do_csum_loop
88
89 add d3,d2
90 beq do_csum_done
91
92do_csum_remainder:
93 # cut 16-31 bytes down to 0-15
94 cmp +16,d2
95 bcs do_csum_fewer_than_16
96 mov (a0+),d0
97 add d0,d1
98 mov (a0+),e0
99 addc e0,d1
100 mov (a0+),e1
101 addc e1,d1
102 mov (a0+),e3
103 addc e3,d1
104 addc +0,d1
105 add -16,d2
106 beq do_csum_done
107
108do_csum_fewer_than_16:
109 # copy the remaining whole words
110 cmp +4,d2
111 bcs do_csum_fewer_than_4
112 cmp +8,d2
113 bcs do_csum_one_word
114 cmp +12,d2
115 bcs do_csum_two_words
116 mov (a0+),d0
117 add d0,d1
118 addc +0,d1
119do_csum_two_words:
120 mov (a0+),d0
121 add d0,d1
122 addc +0,d1
123do_csum_one_word:
124 mov (a0+),d0
125 add d0,d1
126 addc +0,d1
127
128do_csum_fewer_than_4:
129 and +3,d2
130 beq do_csum_done
131 xor_cmp d0,d0,+2,d2
132 bcs do_csum_fewer_than_2
133 movhu (a0+),d0
134do_csum_fewer_than_2:
135 and +1,d2
136 beq do_csum_add_last_bit
137 movbu (a0),d3
138 add d3,d0
139do_csum_add_last_bit:
140 add d0,d1
141 addc +0,d1
142
143do_csum_done:
144 # compress the checksum down to 16 bits
145 mov +0xffff0000,d2
146 and d1,d2
147 asl +16,d1
148 add d2,d1,d0
149 addc +0xffff,d0
150 lsr +16,d0
151
152 # flip the halves of the word result if the buffer was oddly aligned
153 mov (12,sp),d1
154 and +1,d1
155 beq do_csum_not_oddly_aligned
156 swaph d0,d0 # exchange bits 15:8 with 7:0
157
158do_csum_not_oddly_aligned:
159 ret [d2,d3],8
160
161do_csum_end:
162 .size do_csum, do_csum_end-do_csum
diff --git a/arch/mn10300/lib/internal.h b/arch/mn10300/lib/internal.h
new file mode 100644
index 000000000000..0014eee5f04f
--- /dev/null
+++ b/arch/mn10300/lib/internal.h
@@ -0,0 +1,15 @@
1/* Internal definitions for the arch part of the kernel library
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12/*
13 * do_csum.S
14 */
15extern unsigned int do_csum(const unsigned char *, size_t);
diff --git a/arch/mn10300/lib/lshrdi3.c b/arch/mn10300/lib/lshrdi3.c
new file mode 100644
index 000000000000..e05e64e9ce96
--- /dev/null
+++ b/arch/mn10300/lib/lshrdi3.c
@@ -0,0 +1,60 @@
1/* lshrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
2/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public Licence as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public Licence for more details.
15
16You should have received a copy of the GNU General Public Licence
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21#define BITS_PER_UNIT 8
22
23typedef int SItype __attribute__((mode(SI)));
24typedef unsigned int USItype __attribute__((mode(SI)));
25typedef int DItype __attribute__((mode(DI)));
26typedef int word_type __attribute__((mode(__word__)));
27
28struct DIstruct {
29 SItype low;
30 SItype high;
31};
32
33union DIunion {
34 struct DIstruct s;
35 DItype ll;
36};
37
38DItype __lshrdi3(DItype u, word_type b)
39{
40 union DIunion w;
41 word_type bm;
42 union DIunion uu;
43
44 if (b == 0)
45 return u;
46
47 uu.ll = u;
48
49 bm = (sizeof(SItype) * BITS_PER_UNIT) - b;
50 if (bm <= 0) {
51 w.s.high = 0;
52 w.s.low = (USItype) uu.s.high >> -bm;
53 } else {
54 USItype carries = (USItype) uu.s.high << bm;
55 w.s.high = (USItype) uu.s.high >> b;
56 w.s.low = ((USItype) uu.s.low >> b) | carries;
57 }
58
59 return w.ll;
60}
diff --git a/arch/mn10300/lib/memcpy.S b/arch/mn10300/lib/memcpy.S
new file mode 100644
index 000000000000..25fb9bb2604f
--- /dev/null
+++ b/arch/mn10300/lib/memcpy.S
@@ -0,0 +1,135 @@
1/* MN10300 Optimised simple memory to memory copy
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <asm/cache.h>
12
13 .section .text
14 .balign L1_CACHE_BYTES
15
16###############################################################################
17#
18# void *memcpy(void *dst, const void *src, size_t n)
19#
20###############################################################################
21 .globl memcpy
22 .type memcpy,@function
23memcpy:
24 movm [d2,d3],(sp)
25 mov d0,(12,sp)
26 mov d1,(16,sp)
27 mov (20,sp),d2 # count
28 mov d0,a0 # dst
29 mov d1,a1 # src
30 mov d0,e3 # the return value
31
32 cmp +0,d2
33 beq memcpy_done # return if zero-length copy
34
35 # see if the three parameters are all four-byte aligned
36 or d0,d1,d3
37 or d2,d3
38 and +3,d3
39 bne memcpy_1 # jump if not
40
41 # we want to transfer as much as we can in chunks of 32 bytes
42 cmp +31,d2
43 bls memcpy_4_remainder # 4-byte aligned remainder
44
45 movm [exreg1],(sp)
46 add -32,d2
47 mov +32,d3
48
49memcpy_4_loop:
50 mov (a1+),d0
51 mov (a1+),d1
52 mov (a1+),e0
53 mov (a1+),e1
54 mov (a1+),e4
55 mov (a1+),e5
56 mov (a1+),e6
57 mov (a1+),e7
58 mov d0,(a0+)
59 mov d1,(a0+)
60 mov e0,(a0+)
61 mov e1,(a0+)
62 mov e4,(a0+)
63 mov e5,(a0+)
64 mov e6,(a0+)
65 mov e7,(a0+)
66
67 sub d3,d2
68 bcc memcpy_4_loop
69
70 movm (sp),[exreg1]
71 add d3,d2
72 beq memcpy_4_no_remainder
73
74memcpy_4_remainder:
75 # cut 4-7 words down to 0-3
76 cmp +16,d2
77 bcs memcpy_4_three_or_fewer_words
78 mov (a1+),d0
79 mov (a1+),d1
80 mov (a1+),e0
81 mov (a1+),e1
82 mov d0,(a0+)
83 mov d1,(a0+)
84 mov e0,(a0+)
85 mov e1,(a0+)
86 add -16,d2
87 beq memcpy_4_no_remainder
88
89 # copy the remaining 1, 2 or 3 words
90memcpy_4_three_or_fewer_words:
91 cmp +8,d2
92 bcs memcpy_4_one_word
93 beq memcpy_4_two_words
94 mov (a1+),d0
95 mov d0,(a0+)
96memcpy_4_two_words:
97 mov (a1+),d0
98 mov d0,(a0+)
99memcpy_4_one_word:
100 mov (a1+),d0
101 mov d0,(a0+)
102
103memcpy_4_no_remainder:
104 # check we copied the correct amount
105 # TODO: REMOVE CHECK
106 sub e3,a0,d2
107 mov (20,sp),d1
108 cmp d2,d1
109 beq memcpy_done
110 break
111 break
112 break
113
114memcpy_done:
115 mov e3,a0
116 ret [d2,d3],8
117
118 # handle misaligned copying
119memcpy_1:
120 add -1,d2
121 mov +1,d3
122 setlb # setlb requires the next insns
123 # to occupy exactly 4 bytes
124
125 sub d3,d2
126 movbu (a1),d0
127 movbu d0,(a0)
128 add_add d3,a1,d3,a0
129 lcc
130
131 mov e3,a0
132 ret [d2,d3],8
133
134memcpy_end:
135 .size memcpy, memcpy_end-memcpy
diff --git a/arch/mn10300/lib/memmove.S b/arch/mn10300/lib/memmove.S
new file mode 100644
index 000000000000..20b07b62b77c
--- /dev/null
+++ b/arch/mn10300/lib/memmove.S
@@ -0,0 +1,160 @@
1/* MN10300 Optimised simple memory to memory copy, with support for overlapping
2 * regions
3 *
4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public Licence
9 * as published by the Free Software Foundation; either version
10 * 2 of the Licence, or (at your option) any later version.
11 */
12#include <asm/cache.h>
13
14 .section .text
15 .balign L1_CACHE_BYTES
16
17###############################################################################
18#
19# void *memmove(void *dst, const void *src, size_t n)
20#
21###############################################################################
22 .globl memmove
23 .type memmove,@function
24memmove:
25 # fall back to memcpy if dst < src to work bottom up
26 cmp d1,d0
27 bcs memmove_memcpy
28
29 # work top down
30 movm [d2,d3],(sp)
31 mov d0,(12,sp)
32 mov d1,(16,sp)
33 mov (20,sp),d2 # count
34 add d0,d2,a0 # dst end
35 add d1,d2,a1 # src end
36 mov d0,e3 # the return value
37
38 cmp +0,d2
39 beq memmove_done # return if zero-length copy
40
41 # see if the three parameters are all four-byte aligned
42 or d0,d1,d3
43 or d2,d3
44 and +3,d3
45 bne memmove_1 # jump if not
46
47 # we want to transfer as much as we can in chunks of 32 bytes
48 add -4,a1
49 cmp +31,d2
50 bls memmove_4_remainder # 4-byte aligned remainder
51
52 add -32,d2
53 mov +32,d3
54
55memmove_4_loop:
56 mov (a1),d0
57 sub_sub +4,a1,+4,a0
58 mov d0,(a0)
59 mov (a1),d1
60 sub_sub +4,a1,+4,a0
61 mov d1,(a0)
62
63 mov (a1),d0
64 sub_sub +4,a1,+4,a0
65 mov d0,(a0)
66 mov (a1),d1
67 sub_sub +4,a1,+4,a0
68 mov d1,(a0)
69
70 mov (a1),d0
71 sub_sub +4,a1,+4,a0
72 mov d0,(a0)
73 mov (a1),d1
74 sub_sub +4,a1,+4,a0
75 mov d1,(a0)
76
77 mov (a1),d0
78 sub_sub +4,a1,+4,a0
79 mov d0,(a0)
80 mov (a1),d1
81 sub_sub +4,a1,+4,a0
82 mov d1,(a0)
83
84 sub d3,d2
85 bcc memmove_4_loop
86
87 add d3,d2
88 beq memmove_4_no_remainder
89
90memmove_4_remainder:
91 # cut 4-7 words down to 0-3
92 cmp +16,d2
93 bcs memmove_4_three_or_fewer_words
94 mov (a1),d0
95 sub_sub +4,a1,+4,a0
96 mov d0,(a0)
97 mov (a1),d1
98 sub_sub +4,a1,+4,a0
99 mov d1,(a0)
100 mov (a1),e0
101 sub_sub +4,a1,+4,a0
102 mov e0,(a0)
103 mov (a1),e1
104 sub_sub +4,a1,+4,a0
105 mov e1,(a0)
106 add -16,d2
107 beq memmove_4_no_remainder
108
109 # copy the remaining 1, 2 or 3 words
110memmove_4_three_or_fewer_words:
111 cmp +8,d2
112 bcs memmove_4_one_word
113 beq memmove_4_two_words
114 mov (a1),d0
115 sub_sub +4,a1,+4,a0
116 mov d0,(a0)
117memmove_4_two_words:
118 mov (a1),d0
119 sub_sub +4,a1,+4,a0
120 mov d0,(a0)
121memmove_4_one_word:
122 mov (a1),d0
123 sub_sub +4,a1,+4,a0
124 mov d0,(a0)
125
126memmove_4_no_remainder:
127 # check we copied the correct amount
128 # TODO: REMOVE CHECK
129 sub e3,a0,d2
130 beq memmove_done
131 break
132 break
133 break
134
135memmove_done:
136 mov e3,a0
137 ret [d2,d3],8
138
139 # handle misaligned copying
140memmove_1:
141 add -1,a1
142 add -1,d2
143 mov +1,d3
144 setlb # setlb requires the next insns
145 # to occupy exactly 4 bytes
146
147 sub d3,d2
148 movbu (a1),d0
149 sub_sub d3,a1,d3,a0
150 movbu d0,(a0)
151 lcc
152
153 mov e3,a0
154 ret [d2,d3],8
155
156memmove_memcpy:
157 jmp memcpy
158
159memmove_end:
160 .size memmove, memmove_end-memmove
diff --git a/arch/mn10300/lib/memset.S b/arch/mn10300/lib/memset.S
new file mode 100644
index 000000000000..bc02e39629b7
--- /dev/null
+++ b/arch/mn10300/lib/memset.S
@@ -0,0 +1,121 @@
1/* Optimised simple memory fill
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11#include <asm/cache.h>
12
13 .section .text
14 .balign L1_CACHE_BYTES
15
16###############################################################################
17#
18# void *memset(void *dst, int c, size_t n)
19#
20###############################################################################
21 .globl memset
22 .type memset,@function
23memset:
24 movm [d2,d3],(sp)
25 mov d0,(12,sp)
26 mov d1,(16,sp)
27 mov (20,sp),d2 # count
28 mov d0,a0 # dst
29 mov d0,e3 # the return value
30
31 cmp +0,d2
32 beq memset_done # return if zero-length fill
33
34 # see if the region parameters are four-byte aligned
35 or d0,d2,d3
36 and +3,d3
37 bne memset_1 # jump if not
38
39 extbu d1
40 mov_asl d1,d3,8,d1
41 or_asl d1,d3,8,d1
42 or_asl d1,d3,8,d1
43 or d3,d1
44
45 # we want to transfer as much as we can in chunks of 32 bytes
46 cmp +31,d2
47 bls memset_4_remainder # 4-byte aligned remainder
48
49 add -32,d2
50 mov +32,d3
51
52memset_4_loop:
53 mov d1,(a0+)
54 mov d1,(a0+)
55 mov d1,(a0+)
56 mov d1,(a0+)
57 mov d1,(a0+)
58 mov d1,(a0+)
59 mov d1,(a0+)
60 mov d1,(a0+)
61
62 sub d3,d2
63 bcc memset_4_loop
64
65 add d3,d2
66 beq memset_4_no_remainder
67
68memset_4_remainder:
69 # cut 4-7 words down to 0-3
70 cmp +16,d2
71 bcs memset_4_three_or_fewer_words
72 mov d1,(a0+)
73 mov d1,(a0+)
74 mov d1,(a0+)
75 mov d1,(a0+)
76 add -16,d2
77 beq memset_4_no_remainder
78
79 # copy the remaining 1, 2 or 3 words
80memset_4_three_or_fewer_words:
81 cmp +8,d2
82 bcs memset_4_one_word
83 beq memset_4_two_words
84 mov d1,(a0+)
85memset_4_two_words:
86 mov d1,(a0+)
87memset_4_one_word:
88 mov d1,(a0+)
89
90memset_4_no_remainder:
91 # check we set the correct amount
92 # TODO: REMOVE CHECK
93 sub e3,a0,d2
94 mov (20,sp),d1
95 cmp d2,d1
96 beq memset_done
97 break
98 break
99 break
100
101memset_done:
102 mov e3,a0
103 ret [d2,d3],8
104
105 # handle misaligned copying
106memset_1:
107 add -1,d2
108 mov +1,d3
109 setlb # setlb requires the next insns
110 # to occupy exactly 4 bytes
111
112 sub d3,d2
113 movbu d1,(a0)
114 inc a0
115 lcc
116
117 mov e3,a0
118 ret [d2,d3],8
119
120memset_end:
121 .size memset, memset_end-memset
diff --git a/arch/mn10300/lib/negdi2.c b/arch/mn10300/lib/negdi2.c
new file mode 100644
index 000000000000..eae4ecdd5f69
--- /dev/null
+++ b/arch/mn10300/lib/negdi2.c
@@ -0,0 +1,57 @@
1/* More subroutines needed by GCC output code on some machines. */
2/* Compile this one with gcc. */
3/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
4 2000, 2001 Free Software Foundation, Inc.
5
6This file is part of GNU CC.
7
8GNU CC is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public Licence as published by
10the Free Software Foundation; either version 2, or (at your option)
11any later version.
12
13In addition to the permissions in the GNU General Public Licence, the
14Free Software Foundation gives you unlimited permission to link the
15compiled version of this file into combinations with other programs,
16and to distribute those combinations without any restriction coming
17from the use of this file. (The General Public Licence restrictions
18do apply in other respects; for example, they cover modification of
19the file, and distribution when not linked into a combine
20executable.)
21
22GNU CC is distributed in the hope that it will be useful,
23but WITHOUT ANY WARRANTY; without even the implied warranty of
24MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25GNU General Public Licence for more details.
26
27You should have received a copy of the GNU General Public Licence
28along with GNU CC; see the file COPYING. If not, write to
29the Free Software Foundation, 59 Temple Place - Suite 330,
30Boston, MA 02111-1307, USA. */
31
32/* It is incorrect to include config.h here, because this file is being
33 compiled for the target, and hence definitions concerning only the host
34 do not apply. */
35
36#include <linux/types.h>
37
38union DWunion {
39 s64 ll;
40 struct {
41 s32 low;
42 s32 high;
43 } s;
44};
45
46s64 __negdi2(s64 u)
47{
48 union DWunion w;
49 union DWunion uu;
50
51 uu.ll = u;
52
53 w.s.low = -uu.s.low;
54 w.s.high = -uu.s.high - ((u32) w.s.low > 0);
55
56 return w.ll;
57}
diff --git a/arch/mn10300/lib/usercopy.c b/arch/mn10300/lib/usercopy.c
new file mode 100644
index 000000000000..a75b203059c1
--- /dev/null
+++ b/arch/mn10300/lib/usercopy.c
@@ -0,0 +1,166 @@
1/* MN10300 Userspace accessor functions
2 *
3 * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public Licence
9 * as published by the Free Software Foundation; either version
10 * 2 of the Licence, or (at your option) any later version.
11 */
12#include <asm/uaccess.h>
13
14unsigned long
15__generic_copy_to_user(void *to, const void *from, unsigned long n)
16{
17 if (access_ok(VERIFY_WRITE, to, n))
18 __copy_user(to, from, n);
19 return n;
20}
21
22unsigned long
23__generic_copy_from_user(void *to, const void *from, unsigned long n)
24{
25 if (access_ok(VERIFY_READ, from, n))
26 __copy_user_zeroing(to, from, n);
27 return n;
28}
29
30/*
31 * Copy a null terminated string from userspace.
32 */
33#define __do_strncpy_from_user(dst, src, count, res) \
34do { \
35 int w; \
36 asm volatile( \
37 " mov %1,%0\n" \
38 " cmp 0,%1\n" \
39 " beq 2f\n" \
40 "0:\n" \
41 " movbu (%5),%2\n" \
42 "1:\n" \
43 " movbu %2,(%6)\n" \
44 " inc %5\n" \
45 " inc %6\n" \
46 " cmp 0,%2\n" \
47 " beq 2f\n" \
48 " add -1,%1\n" \
49 " bne 0b\n" \
50 "2:\n" \
51 " sub %1,%0\n" \
52 "3:\n" \
53 " .section .fixup,\"ax\"\n" \
54 "4:\n" \
55 " mov %3,%0\n" \
56 " jmp 3b\n" \
57 " .previous\n" \
58 " .section __ex_table,\"a\"\n" \
59 " .balign 4\n" \
60 " .long 0b,4b\n" \
61 " .long 1b,4b\n" \
62 " .previous" \
63 :"=&r"(res), "=r"(count), "=&r"(w) \
64 :"i"(-EFAULT), "1"(count), "a"(src), "a"(dst) \
65 :"memory"); \
66} while (0)
67
68long
69__strncpy_from_user(char *dst, const char *src, long count)
70{
71 long res;
72 __do_strncpy_from_user(dst, src, count, res);
73 return res;
74}
75
76long
77strncpy_from_user(char *dst, const char *src, long count)
78{
79 long res = -EFAULT;
80 if (access_ok(VERIFY_READ, src, 1))
81 __do_strncpy_from_user(dst, src, count, res);
82 return res;
83}
84
85
86/*
87 * Clear a userspace memory
88 */
89#define __do_clear_user(addr, size) \
90do { \
91 int w; \
92 asm volatile( \
93 " cmp 0,%0\n" \
94 " beq 1f\n" \
95 " clr %1\n" \
96 "0: movbu %1,(%3,%2)\n" \
97 " inc %3\n" \
98 " cmp %0,%3\n" \
99 " bne 0b\n" \
100 "1:\n" \
101 " sub %3,%0\n" \
102 "2:\n" \
103 ".section .fixup,\"ax\"\n" \
104 "3: jmp 2b\n" \
105 ".previous\n" \
106 ".section __ex_table,\"a\"\n" \
107 " .balign 4\n" \
108 " .long 0b,3b\n" \
109 ".previous\n" \
110 : "+r"(size), "=&r"(w) \
111 : "a"(addr), "d"(0) \
112 : "memory"); \
113} while (0)
114
115unsigned long
116__clear_user(void *to, unsigned long n)
117{
118 __do_clear_user(to, n);
119 return n;
120}
121
122unsigned long
123clear_user(void *to, unsigned long n)
124{
125 if (access_ok(VERIFY_WRITE, to, n))
126 __do_clear_user(to, n);
127 return n;
128}
129
130/*
131 * Return the size of a string (including the ending 0)
132 *
133 * Return 0 on exception, a value greater than N if too long
134 */
135long strnlen_user(const char *s, long n)
136{
137 unsigned long res, w;
138
139 if (!__addr_ok(s))
140 return 0;
141
142 if (n < 0 || n + (u_long) s > current_thread_info()->addr_limit.seg)
143 n = current_thread_info()->addr_limit.seg - (u_long)s;
144
145 asm volatile(
146 "0: cmp %4,%0\n"
147 " beq 2f\n"
148 "1: movbu (%0,%3),%1\n"
149 " inc %0\n"
150 " cmp 0,%1\n"
151 " beq 3f\n"
152 " bra 0b\n"
153 "2: clr %0\n"
154 "3:\n"
155 ".section .fixup,\"ax\"\n"
156 "4: jmp 2b\n"
157 ".previous\n"
158 ".section __ex_table,\"a\"\n"
159 " .balign 4\n"
160 " .long 1b,4b\n"
161 ".previous\n"
162 :"=d"(res), "=&r"(w)
163 :"0"(0), "a"(s), "r"(n)
164 :"memory");
165 return res;
166}