1 /* SPDX-License-Identifier: GPL-2.0 */
3 * copy_page, __copy_user_page, __copy_user implementation of SuperH
5 * Copyright (C) 2001 Niibe Yutaka & Kaz Kojima
6 * Copyright (C) 2002 Toshinobu Sugioka
7 * Copyright (C) 2006 Paul Mundt
9 #include <linux/linkage.h>
17 * void copy_page(void *to, void *from)
21 * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch
22 * r8 --- from + PAGE_SIZE
34 mov #(PAGE_SIZE >> 10), r0
47 #if defined(CONFIG_CPU_SH4)
71 * __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
72 * Return the number of bytes NOT copied
76 .section __ex_table, "a"; \
77 .long 9999b, 6000f ; \
79 #define EX_NO_POP(...) \
81 .section __ex_table, "a"; \
82 .long 9999b, 6005f ; \
85 ! Check if small number of bytes
88 cmp/gt r0,r6 ! r6 (len) > r0 (11)
89 bf/s .L_cleanup_loop_no_pop
90 add r6,r3 ! last destination address
92 ! Calculate bytes needed to align to src
104 ! Copy bytes to long word align src
112 ! Jump to appropriate routine depending on dest
131 * Come here if there are less than 12 bytes to copy
133 * Keep the branch target close, so the bf/s callee doesn't overflow
134 * and result in a more expensive branch being inserted. This is the
135 * fast-path for small copies, the jump via the jump table will hit the
136 * default slow-path cleanup. -PFM.
138 .L_cleanup_loop_no_pop:
139 tst r6,r6 ! Check explicitly for zero
143 EX_NO_POP( mov.b @r5+,r0 )
145 EX_NO_POP( mov.b r0,@r4 )
149 1: mov #0,r0 ! normal return
153 .section .fixup, "ax"
169 ! Skip the large copy for small transfers
171 cmp/gt r6, r0 ! r0 (60) > r6 (len)
174 ! Align dest to a 32 byte boundary
199 #ifdef CONFIG_CPU_SH4
205 EX( mov.l r1,@(4,r4) )
207 EX( mov.l r2,@(8,r4) )
208 cmp/gt r6, r0 ! r0 (32) > r6 (len)
209 EX( mov.l r7,@(12,r4) )
210 EX( mov.l r8,@(16,r4) )
211 EX( mov.l r9,@(20,r4) )
212 EX( mov.l r10,@(24,r4) )
213 EX( mov.l r11,@(28,r4) )
243 #ifdef CONFIG_CPU_LITTLE_ENDIAN
257 EX( mov.l r1,@(4,r4) )
258 EX( mov.l r8,@(8,r4) )
259 EX( mov.l r9,@(12,r4) )
268 EX( mov.l r10,@(16,r4) )
269 EX( mov.l r1,@(20,r4) )
270 EX( mov.l r8,@(24,r4) )
271 EX( mov.w r0,@(28,r4) )
275 EX( mov.l @(28,r5),r0 )
276 EX( mov.l @(24,r5),r8 )
277 EX( mov.l @(20,r5),r9 )
278 EX( mov.l @(16,r5),r10 )
279 EX( mov.w r0,@(30,r4) )
284 EX( mov.l r0,@(28,r4) )
285 EX( mov.l r8,@(24,r4) )
286 EX( mov.l r9,@(20,r4) )
288 EX( mov.l @(12,r5),r0 )
289 EX( mov.l @(8,r5),r8 )
291 EX( mov.l @(4,r5),r9 )
297 EX( mov.l r0,@(12,r4) )
298 EX( mov.l r8,@(8,r4) )
300 EX( mov.l r9,@(4,r4) )
301 EX( mov.w r0,@(2,r4) )
310 1: ! Read longword, write two words per iteration
313 #ifdef CONFIG_CPU_LITTLE_ENDIAN
316 EX( mov.w r0,@(2,r4) )
318 EX( mov.w r0,@(2,r4) )
328 ! Destination = 01 or 11
332 ! Read longword, write byte, word, byte per iteration
335 #ifdef CONFIG_CPU_LITTLE_ENDIAN
341 EX( mov.b r0,@(2,r4) )
345 EX( mov.b r0,@(3,r4) )
355 ! Cleanup last few bytes
371 mov #0,r0 ! normal return
376 .section .fixup, "ax"