aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/lib
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/lib')
-rw-r--r--arch/sh/lib/Makefile5
-rw-r--r--arch/sh/lib/clear_page.S154
-rw-r--r--arch/sh/lib/copy_page.S389
-rw-r--r--arch/sh/lib/io.c82
4 files changed, 628 insertions, 2 deletions
diff --git a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile
index 9dc7b6985052..ebb55d1149f5 100644
--- a/arch/sh/lib/Makefile
+++ b/arch/sh/lib/Makefile
@@ -2,12 +2,13 @@
2# Makefile for SuperH-specific library files.. 2# Makefile for SuperH-specific library files..
3# 3#
4 4
5lib-y = delay.o memset.o memmove.o memchr.o \ 5lib-y = delay.o io.o memset.o memmove.o memchr.o \
6 checksum.o strlen.o div64.o div64-generic.o 6 checksum.o strlen.o div64.o div64-generic.o
7 7
8memcpy-y := memcpy.o 8memcpy-y := memcpy.o
9memcpy-$(CONFIG_CPU_SH4) := memcpy-sh4.o 9memcpy-$(CONFIG_CPU_SH4) := memcpy-sh4.o
10 10
11lib-y += $(memcpy-y) 11lib-$(CONFIG_MMU) += copy_page.o clear_page.o
12lib-y += $(memcpy-y)
12 13
13EXTRA_CFLAGS += -Werror 14EXTRA_CFLAGS += -Werror
diff --git a/arch/sh/lib/clear_page.S b/arch/sh/lib/clear_page.S
new file mode 100644
index 000000000000..3539123fe517
--- /dev/null
+++ b/arch/sh/lib/clear_page.S
@@ -0,0 +1,154 @@
1/*
2 * __clear_user_page, __clear_user, clear_page implementation of SuperH
3 *
4 * Copyright (C) 2001 Kaz Kojima
5 * Copyright (C) 2001, 2002 Niibe Yutaka
6 * Copyright (C) 2006 Paul Mundt
7 */
8#include <linux/linkage.h>
9#include <asm/page.h>
10
11/*
12 * clear_page
13 * @to: P1 address
14 *
15 * void clear_page(void *to)
16 */
17
18/*
19 * r0 --- scratch
20 * r4 --- to
21 * r5 --- to + PAGE_SIZE
22 */
23ENTRY(clear_page)
24 mov r4,r5
25 mov.l .Llimit,r0
26 add r0,r5
27 mov #0,r0
28 !
291:
30#if defined(CONFIG_CPU_SH3)
31 mov.l r0,@r4
32#elif defined(CONFIG_CPU_SH4)
33 movca.l r0,@r4
34 mov r4,r1
35#endif
36 add #32,r4
37 mov.l r0,@-r4
38 mov.l r0,@-r4
39 mov.l r0,@-r4
40 mov.l r0,@-r4
41 mov.l r0,@-r4
42 mov.l r0,@-r4
43 mov.l r0,@-r4
44#if defined(CONFIG_CPU_SH4)
45 ocbwb @r1
46#endif
47 cmp/eq r5,r4
48 bf/s 1b
49 add #28,r4
50 !
51 rts
52 nop
53
54 .balign 4
55.Llimit: .long (PAGE_SIZE-28)
56
57ENTRY(__clear_user)
58 !
59 mov #0, r0
60 mov #0xe0, r1 ! 0xffffffe0
61 !
62 ! r4..(r4+31)&~32 -------- not aligned [ Area 0 ]
63 ! (r4+31)&~32..(r4+r5)&~32 -------- aligned [ Area 1 ]
64 ! (r4+r5)&~32..r4+r5 -------- not aligned [ Area 2 ]
65 !
66 ! Clear area 0
67 mov r4, r2
68 !
69 tst r1, r5 ! length < 32
70 bt .Larea2 ! skip to remainder
71 !
72 add #31, r2
73 and r1, r2
74 cmp/eq r4, r2
75 bt .Larea1
76 mov r2, r3
77 sub r4, r3
78 mov r3, r7
79 mov r4, r2
80 !
81.L0: dt r3
820: mov.b r0, @r2
83 bf/s .L0
84 add #1, r2
85 !
86 sub r7, r5
87 mov r2, r4
88.Larea1:
89 mov r4, r3
90 add r5, r3
91 and r1, r3
92 cmp/hi r2, r3
93 bf .Larea2
94 !
95 ! Clear area 1
96#if defined(CONFIG_CPU_SH4)
971: movca.l r0, @r2
98#else
991: mov.l r0, @r2
100#endif
101 add #4, r2
1022: mov.l r0, @r2
103 add #4, r2
1043: mov.l r0, @r2
105 add #4, r2
1064: mov.l r0, @r2
107 add #4, r2
1085: mov.l r0, @r2
109 add #4, r2
1106: mov.l r0, @r2
111 add #4, r2
1127: mov.l r0, @r2
113 add #4, r2
1148: mov.l r0, @r2
115 add #4, r2
116 cmp/hi r2, r3
117 bt/s 1b
118 nop
119 !
120 ! Clear area 2
121.Larea2:
122 mov r4, r3
123 add r5, r3
124 cmp/hs r3, r2
125 bt/s .Ldone
126 sub r2, r3
127.L2: dt r3
1289: mov.b r0, @r2
129 bf/s .L2
130 add #1, r2
131 !
132.Ldone: rts
133 mov #0, r0 ! return 0 as normal return
134
135 ! return the number of bytes remained
136.Lbad_clear_user:
137 mov r4, r0
138 add r5, r0
139 rts
140 sub r2, r0
141
142.section __ex_table,"a"
143 .align 2
144 .long 0b, .Lbad_clear_user
145 .long 1b, .Lbad_clear_user
146 .long 2b, .Lbad_clear_user
147 .long 3b, .Lbad_clear_user
148 .long 4b, .Lbad_clear_user
149 .long 5b, .Lbad_clear_user
150 .long 6b, .Lbad_clear_user
151 .long 7b, .Lbad_clear_user
152 .long 8b, .Lbad_clear_user
153 .long 9b, .Lbad_clear_user
154.previous
diff --git a/arch/sh/lib/copy_page.S b/arch/sh/lib/copy_page.S
new file mode 100644
index 000000000000..e002b91c8752
--- /dev/null
+++ b/arch/sh/lib/copy_page.S
@@ -0,0 +1,389 @@
1/*
2 * copy_page, __copy_user_page, __copy_user implementation of SuperH
3 *
4 * Copyright (C) 2001 Niibe Yutaka & Kaz Kojima
5 * Copyright (C) 2002 Toshinobu Sugioka
6 * Copyright (C) 2006 Paul Mundt
7 */
8#include <linux/linkage.h>
9#include <asm/page.h>
10
11/*
12 * copy_page
13 * @to: P1 address
14 * @from: P1 address
15 *
16 * void copy_page(void *to, void *from)
17 */
18
19/*
20 * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch
21 * r8 --- from + PAGE_SIZE
22 * r9 --- not used
23 * r10 --- to
24 * r11 --- from
25 */
26ENTRY(copy_page)
27 mov.l r8,@-r15
28 mov.l r10,@-r15
29 mov.l r11,@-r15
30 mov r4,r10
31 mov r5,r11
32 mov r5,r8
33 mov.l .Lpsz,r0
34 add r0,r8
35 !
361: mov.l @r11+,r0
37 mov.l @r11+,r1
38 mov.l @r11+,r2
39 mov.l @r11+,r3
40 mov.l @r11+,r4
41 mov.l @r11+,r5
42 mov.l @r11+,r6
43 mov.l @r11+,r7
44#if defined(CONFIG_CPU_SH3)
45 mov.l r0,@r10
46#elif defined(CONFIG_CPU_SH4)
47 movca.l r0,@r10
48 mov r10,r0
49#endif
50 add #32,r10
51 mov.l r7,@-r10
52 mov.l r6,@-r10
53 mov.l r5,@-r10
54 mov.l r4,@-r10
55 mov.l r3,@-r10
56 mov.l r2,@-r10
57 mov.l r1,@-r10
58#if defined(CONFIG_CPU_SH4)
59 ocbwb @r0
60#endif
61 cmp/eq r11,r8
62 bf/s 1b
63 add #28,r10
64 !
65 mov.l @r15+,r11
66 mov.l @r15+,r10
67 mov.l @r15+,r8
68 rts
69 nop
70
71 .balign 4
72.Lpsz: .long PAGE_SIZE
73
74/*
75 * __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
76 * Return the number of bytes NOT copied
77 */
78#define EX(...) \
79 9999: __VA_ARGS__ ; \
80 .section __ex_table, "a"; \
81 .long 9999b, 6000f ; \
82 .previous
83ENTRY(__copy_user)
84 ! Check if small number of bytes
85 mov #11,r0
86 mov r4,r3
87 cmp/gt r0,r6 ! r6 (len) > r0 (11)
88 bf/s .L_cleanup_loop_no_pop
89 add r6,r3 ! last destination address
90
91 ! Calculate bytes needed to align to src
92 mov.l r11,@-r15
93 neg r5,r0
94 mov.l r10,@-r15
95 add #4,r0
96 mov.l r9,@-r15
97 and #3,r0
98 mov.l r8,@-r15
99 tst r0,r0
100 bt 2f
101
1021:
103 ! Copy bytes to long word align src
104EX( mov.b @r5+,r1 )
105 dt r0
106 add #-1,r6
107EX( mov.b r1,@r4 )
108 bf/s 1b
109 add #1,r4
110
111 ! Jump to appropriate routine depending on dest
1122: mov #3,r1
113 mov r6, r2
114 and r4,r1
115 shlr2 r2
116 shll2 r1
117 mova .L_jump_tbl,r0
118 mov.l @(r0,r1),r1
119 jmp @r1
120 nop
121
122 .align 2
123.L_jump_tbl:
124 .long .L_dest00
125 .long .L_dest01
126 .long .L_dest10
127 .long .L_dest11
128
129/*
130 * Come here if there are less than 12 bytes to copy
131 *
132 * Keep the branch target close, so the bf/s callee doesn't overflow
133 * and result in a more expensive branch being inserted. This is the
134 * fast-path for small copies, the jump via the jump table will hit the
135 * default slow-path cleanup. -PFM.
136 */
137.L_cleanup_loop_no_pop:
138 tst r6,r6 ! Check explicitly for zero
139 bt 1f
140
1412:
142EX( mov.b @r5+,r0 )
143 dt r6
144EX( mov.b r0,@r4 )
145 bf/s 2b
146 add #1,r4
147
1481: mov #0,r0 ! normal return
1495000:
150
151# Exception handler:
152.section .fixup, "ax"
1536000:
154 mov.l 8000f,r1
155 mov r3,r0
156 jmp @r1
157 sub r4,r0
158 .align 2
1598000: .long 5000b
160
161.previous
162 rts
163 nop
164
165! Destination = 00
166
167.L_dest00:
168 ! Skip the large copy for small transfers
169 mov #(32+32-4), r0
170 cmp/gt r6, r0 ! r0 (60) > r6 (len)
171 bt 1f
172
173 ! Align dest to a 32 byte boundary
174 neg r4,r0
175 add #0x20, r0
176 and #0x1f, r0
177 tst r0, r0
178 bt 2f
179
180 sub r0, r6
181 shlr2 r0
1823:
183EX( mov.l @r5+,r1 )
184 dt r0
185EX( mov.l r1,@r4 )
186 bf/s 3b
187 add #4,r4
188
1892:
190EX( mov.l @r5+,r0 )
191EX( mov.l @r5+,r1 )
192EX( mov.l @r5+,r2 )
193EX( mov.l @r5+,r7 )
194EX( mov.l @r5+,r8 )
195EX( mov.l @r5+,r9 )
196EX( mov.l @r5+,r10 )
197EX( mov.l @r5+,r11 )
198#ifdef CONFIG_CPU_SH4
199EX( movca.l r0,@r4 )
200#else
201EX( mov.l r0,@r4 )
202#endif
203 add #-32, r6
204EX( mov.l r1,@(4,r4) )
205 mov #32, r0
206EX( mov.l r2,@(8,r4) )
207 cmp/gt r6, r0 ! r0 (32) > r6 (len)
208EX( mov.l r7,@(12,r4) )
209EX( mov.l r8,@(16,r4) )
210EX( mov.l r9,@(20,r4) )
211EX( mov.l r10,@(24,r4) )
212EX( mov.l r11,@(28,r4) )
213 bf/s 2b
214 add #32,r4
215
2161: mov r6, r0
217 shlr2 r0
218 tst r0, r0
219 bt .L_cleanup
2201:
221EX( mov.l @r5+,r1 )
222 dt r0
223EX( mov.l r1,@r4 )
224 bf/s 1b
225 add #4,r4
226
227 bra .L_cleanup
228 nop
229
230! Destination = 10
231
232.L_dest10:
233 mov r2,r7
234 shlr2 r7
235 shlr r7
236 tst r7,r7
237 mov #7,r0
238 bt/s 1f
239 and r0,r2
2402:
241 dt r7
242#ifdef CONFIG_CPU_LITTLE_ENDIAN
243EX( mov.l @r5+,r0 )
244EX( mov.l @r5+,r1 )
245EX( mov.l @r5+,r8 )
246EX( mov.l @r5+,r9 )
247EX( mov.l @r5+,r10 )
248EX( mov.w r0,@r4 )
249 add #2,r4
250 xtrct r1,r0
251 xtrct r8,r1
252 xtrct r9,r8
253 xtrct r10,r9
254
255EX( mov.l r0,@r4 )
256EX( mov.l r1,@(4,r4) )
257EX( mov.l r8,@(8,r4) )
258EX( mov.l r9,@(12,r4) )
259
260EX( mov.l @r5+,r1 )
261EX( mov.l @r5+,r8 )
262EX( mov.l @r5+,r0 )
263 xtrct r1,r10
264 xtrct r8,r1
265 xtrct r0,r8
266 shlr16 r0
267EX( mov.l r10,@(16,r4) )
268EX( mov.l r1,@(20,r4) )
269EX( mov.l r8,@(24,r4) )
270EX( mov.w r0,@(28,r4) )
271 bf/s 2b
272 add #30,r4
273#else
274EX( mov.l @(28,r5),r0 )
275EX( mov.l @(24,r5),r8 )
276EX( mov.l @(20,r5),r9 )
277EX( mov.l @(16,r5),r10 )
278EX( mov.w r0,@(30,r4) )
279 add #-2,r4
280 xtrct r8,r0
281 xtrct r9,r8
282 xtrct r10,r9
283EX( mov.l r0,@(28,r4) )
284EX( mov.l r8,@(24,r4) )
285EX( mov.l r9,@(20,r4) )
286
287EX( mov.l @(12,r5),r0 )
288EX( mov.l @(8,r5),r8 )
289 xtrct r0,r10
290EX( mov.l @(4,r5),r9 )
291 mov.l r10,@(16,r4)
292EX( mov.l @r5,r10 )
293 xtrct r8,r0
294 xtrct r9,r8
295 xtrct r10,r9
296EX( mov.l r0,@(12,r4) )
297EX( mov.l r8,@(8,r4) )
298 swap.w r10,r0
299EX( mov.l r9,@(4,r4) )
300EX( mov.w r0,@(2,r4) )
301
302 add #32,r5
303 bf/s 2b
304 add #34,r4
305#endif
306 tst r2,r2
307 bt .L_cleanup
308
3091: ! Read longword, write two words per iteration
310EX( mov.l @r5+,r0 )
311 dt r2
312#ifdef CONFIG_CPU_LITTLE_ENDIAN
313EX( mov.w r0,@r4 )
314 shlr16 r0
315EX( mov.w r0,@(2,r4) )
316#else
317EX( mov.w r0,@(2,r4) )
318 shlr16 r0
319EX( mov.w r0,@r4 )
320#endif
321 bf/s 1b
322 add #4,r4
323
324 bra .L_cleanup
325 nop
326
327! Destination = 01 or 11
328
329.L_dest01:
330.L_dest11:
331 ! Read longword, write byte, word, byte per iteration
332EX( mov.l @r5+,r0 )
333 dt r2
334#ifdef CONFIG_CPU_LITTLE_ENDIAN
335EX( mov.b r0,@r4 )
336 shlr8 r0
337 add #1,r4
338EX( mov.w r0,@r4 )
339 shlr16 r0
340EX( mov.b r0,@(2,r4) )
341 bf/s .L_dest01
342 add #3,r4
343#else
344EX( mov.b r0,@(3,r4) )
345 shlr8 r0
346 swap.w r0,r7
347EX( mov.b r7,@r4 )
348 add #1,r4
349EX( mov.w r0,@r4 )
350 bf/s .L_dest01
351 add #3,r4
352#endif
353
354! Cleanup last few bytes
355.L_cleanup:
356 mov r6,r0
357 and #3,r0
358 tst r0,r0
359 bt .L_exit
360 mov r0,r6
361
362.L_cleanup_loop:
363EX( mov.b @r5+,r0 )
364 dt r6
365EX( mov.b r0,@r4 )
366 bf/s .L_cleanup_loop
367 add #1,r4
368
369.L_exit:
370 mov #0,r0 ! normal return
371
3725000:
373
374# Exception handler:
375.section .fixup, "ax"
3766000:
377 mov.l 8000f,r1
378 mov r3,r0
379 jmp @r1
380 sub r4,r0
381 .align 2
3828000: .long 5000b
383
384.previous
385 mov.l @r15+,r8
386 mov.l @r15+,r9
387 mov.l @r15+,r10
388 rts
389 mov.l @r15+,r11
diff --git a/arch/sh/lib/io.c b/arch/sh/lib/io.c
new file mode 100644
index 000000000000..4f54ec43516f
--- /dev/null
+++ b/arch/sh/lib/io.c
@@ -0,0 +1,82 @@
1/*
2 * arch/sh/lib/io.c - SH32 optimized I/O routines
3 *
4 * Copyright (C) 2000 Stuart Menefy
5 * Copyright (C) 2005 Paul Mundt
6 *
7 * Provide real functions which expand to whatever the header file defined.
8 * Also definitions of machine independent IO functions.
9 *
10 * This file is subject to the terms and conditions of the GNU General Public
11 * License. See the file "COPYING" in the main directory of this archive
12 * for more details.
13 */
14#include <linux/module.h>
15#include <linux/io.h>
16
17void __raw_readsl(unsigned long addr, void *datap, int len)
18{
19 u32 *data;
20
21 for (data = datap; (len != 0) && (((u32)data & 0x1f) != 0); len--)
22 *data++ = ctrl_inl(addr);
23
24 if (likely(len >= (0x20 >> 2))) {
25 int tmp2, tmp3, tmp4, tmp5, tmp6;
26
27 __asm__ __volatile__(
28 "1: \n\t"
29 "mov.l @%7, r0 \n\t"
30 "mov.l @%7, %2 \n\t"
31#ifdef CONFIG_CPU_SH4
32 "movca.l r0, @%0 \n\t"
33#else
34 "mov.l r0, @%0 \n\t"
35#endif
36 "mov.l @%7, %3 \n\t"
37 "mov.l @%7, %4 \n\t"
38 "mov.l @%7, %5 \n\t"
39 "mov.l @%7, %6 \n\t"
40 "mov.l @%7, r7 \n\t"
41 "mov.l @%7, r0 \n\t"
42 "mov.l %2, @(0x04,%0) \n\t"
43 "mov #0x20>>2, %2 \n\t"
44 "mov.l %3, @(0x08,%0) \n\t"
45 "sub %2, %1 \n\t"
46 "mov.l %4, @(0x0c,%0) \n\t"
47 "cmp/hi %1, %2 ! T if 32 > len \n\t"
48 "mov.l %5, @(0x10,%0) \n\t"
49 "mov.l %6, @(0x14,%0) \n\t"
50 "mov.l r7, @(0x18,%0) \n\t"
51 "mov.l r0, @(0x1c,%0) \n\t"
52 "bf.s 1b \n\t"
53 " add #0x20, %0 \n\t"
54 : "=&r" (data), "=&r" (len),
55 "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4),
56 "=&r" (tmp5), "=&r" (tmp6)
57 : "r"(addr), "0" (data), "1" (len)
58 : "r0", "r7", "t", "memory");
59 }
60
61 for (; len != 0; len--)
62 *data++ = ctrl_inl(addr);
63}
64EXPORT_SYMBOL(__raw_readsl);
65
66void __raw_writesl(unsigned long addr, const void *data, int len)
67{
68 if (likely(len != 0)) {
69 int tmp1;
70
71 __asm__ __volatile__ (
72 "1: \n\t"
73 "mov.l @%0+, %1 \n\t"
74 "dt %3 \n\t"
75 "bf.s 1b \n\t"
76 " mov.l %1, @%4 \n\t"
77 : "=&r" (data), "=&r" (tmp1)
78 : "0" (data), "r" (len), "r"(addr)
79 : "t", "memory");
80 }
81}
82EXPORT_SYMBOL(__raw_writesl);