~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/sh/lib/copy_page.S

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0 */
  2 /*
  3  * copy_page, __copy_user_page, __copy_user implementation of SuperH
  4  *
  5  * Copyright (C) 2001  Niibe Yutaka & Kaz Kojima
  6  * Copyright (C) 2002  Toshinobu Sugioka
  7  * Copyright (C) 2006  Paul Mundt
  8  */
  9 #include <linux/linkage.h>
 10 #include <asm/page.h>
 11 
 12 /*
 13  * copy_page
 14  * @to: P1 address
 15  * @from: P1 address
 16  *
 17  * void copy_page(void *to, void *from)
 18  */
 19 
 20 /*
 21  * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch 
 22  * r8 --- from + PAGE_SIZE
 23  * r9 --- not used
 24  * r10 --- to
 25  * r11 --- from
 26  */
 27 ENTRY(copy_page)
 28         mov.l   r8,@-r15
 29         mov.l   r10,@-r15
 30         mov.l   r11,@-r15
 31         mov     r4,r10
 32         mov     r5,r11
 33         mov     r5,r8
 34         mov     #(PAGE_SIZE >> 10), r0
 35         shll8   r0
 36         shll2   r0
 37         add     r0,r8
 38         !
 39 1:      mov.l   @r11+,r0
 40         mov.l   @r11+,r1
 41         mov.l   @r11+,r2
 42         mov.l   @r11+,r3
 43         mov.l   @r11+,r4
 44         mov.l   @r11+,r5
 45         mov.l   @r11+,r6
 46         mov.l   @r11+,r7
 47 #if defined(CONFIG_CPU_SH4)
 48         movca.l r0,@r10
 49 #else
 50         mov.l   r0,@r10
 51 #endif
 52         add     #32,r10
 53         mov.l   r7,@-r10
 54         mov.l   r6,@-r10
 55         mov.l   r5,@-r10
 56         mov.l   r4,@-r10
 57         mov.l   r3,@-r10
 58         mov.l   r2,@-r10
 59         mov.l   r1,@-r10
 60         cmp/eq  r11,r8
 61         bf/s    1b
 62          add    #28,r10
 63         !
 64         mov.l   @r15+,r11
 65         mov.l   @r15+,r10
 66         mov.l   @r15+,r8
 67         rts
 68          nop
 69 
 70 /*
 71  * __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
 72  * Return the number of bytes NOT copied
 73  */
 74 #define EX(...)                 \
 75         9999: __VA_ARGS__ ;             \
 76         .section __ex_table, "a";       \
 77         .long 9999b, 6000f      ;       \
 78         .previous
 79 #define EX_NO_POP(...)                  \
 80         9999: __VA_ARGS__ ;             \
 81         .section __ex_table, "a";       \
 82         .long 9999b, 6005f      ;       \
 83         .previous
 84 ENTRY(__copy_user)
 85         ! Check if small number of bytes
 86         mov     #11,r0
 87         mov     r4,r3
 88         cmp/gt  r0,r6           ! r6 (len) > r0 (11)
 89         bf/s    .L_cleanup_loop_no_pop
 90          add    r6,r3           ! last destination address
 91 
 92         ! Calculate bytes needed to align to src
 93         mov.l   r11,@-r15
 94         neg     r5,r0
 95         mov.l   r10,@-r15
 96         add     #4,r0
 97         mov.l   r9,@-r15
 98         and     #3,r0
 99         mov.l   r8,@-r15
100         tst     r0,r0
101         bt      2f
102 
103 1:
104         ! Copy bytes to long word align src
105 EX(     mov.b   @r5+,r1         )
106         dt      r0
107         add     #-1,r6
108 EX(     mov.b   r1,@r4          )
109         bf/s    1b
110          add    #1,r4
111 
112         ! Jump to appropriate routine depending on dest
113 2:      mov     #3,r1
114         mov     r6, r2
115         and     r4,r1
116         shlr2   r2
117         shll2   r1
118         mova    .L_jump_tbl,r0
119         mov.l   @(r0,r1),r1
120         jmp     @r1
121          nop
122 
123         .align 2
124 .L_jump_tbl:
125         .long   .L_dest00
126         .long   .L_dest01
127         .long   .L_dest10
128         .long   .L_dest11
129 
130 /*
131  * Come here if there are less than 12 bytes to copy
132  *
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.
137  */
138 .L_cleanup_loop_no_pop:
139         tst     r6,r6           ! Check explicitly for zero
140         bt      1f
141 
142 2:
143 EX_NO_POP(      mov.b   @r5+,r0         )
144         dt      r6
145 EX_NO_POP(      mov.b   r0,@r4          )
146         bf/s    2b
147          add    #1,r4
148 
149 1:      mov     #0,r0           ! normal return
150 5000:
151 
152 # Exception handler:
153 .section .fixup, "ax"
154 6005:
155         mov.l   8000f,r1
156         mov     r3,r0
157         jmp     @r1
158          sub    r4,r0
159         .align  2
160 8000:   .long   5000b
161 
162 .previous
163         rts
164          nop
165 
166 ! Destination = 00
167 
168 .L_dest00:
169         ! Skip the large copy for small transfers
170         mov     #(32+32-4), r0
171         cmp/gt  r6, r0          ! r0 (60) > r6 (len)
172         bt      1f
173 
174         ! Align dest to a 32 byte boundary
175         neg     r4,r0
176         add     #0x20, r0
177         and     #0x1f, r0
178         tst     r0, r0
179         bt      2f
180 
181         sub     r0, r6
182         shlr2   r0
183 3:
184 EX(     mov.l   @r5+,r1         )
185         dt      r0
186 EX(     mov.l   r1,@r4          )
187         bf/s    3b
188          add    #4,r4
189 
190 2:
191 EX(     mov.l   @r5+,r0         )
192 EX(     mov.l   @r5+,r1         )
193 EX(     mov.l   @r5+,r2         )
194 EX(     mov.l   @r5+,r7         )
195 EX(     mov.l   @r5+,r8         )
196 EX(     mov.l   @r5+,r9         )
197 EX(     mov.l   @r5+,r10        )
198 EX(     mov.l   @r5+,r11        )
199 #ifdef CONFIG_CPU_SH4
200 EX(     movca.l r0,@r4          )
201 #else
202 EX(     mov.l   r0,@r4          )
203 #endif
204         add     #-32, r6
205 EX(     mov.l   r1,@(4,r4)      )
206         mov     #32, r0
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)    )
214         bf/s    2b
215          add    #32,r4
216 
217 1:      mov     r6, r0
218         shlr2   r0
219         tst     r0, r0
220         bt      .L_cleanup
221 1:
222 EX(     mov.l   @r5+,r1         )
223         dt      r0
224 EX(     mov.l   r1,@r4          )
225         bf/s    1b
226          add    #4,r4
227 
228         bra     .L_cleanup
229          nop
230 
231 ! Destination = 10
232 
233 .L_dest10:
234         mov     r2,r7
235         shlr2   r7
236         shlr    r7
237         tst     r7,r7
238         mov     #7,r0
239         bt/s    1f
240          and    r0,r2
241 2:
242         dt      r7
243 #ifdef CONFIG_CPU_LITTLE_ENDIAN
244 EX(     mov.l   @r5+,r0         )
245 EX(     mov.l   @r5+,r1         )
246 EX(     mov.l   @r5+,r8         )
247 EX(     mov.l   @r5+,r9         )
248 EX(     mov.l   @r5+,r10        )
249 EX(     mov.w   r0,@r4          )
250         add     #2,r4
251         xtrct   r1,r0
252         xtrct   r8,r1
253         xtrct   r9,r8
254         xtrct   r10,r9
255 
256 EX(     mov.l   r0,@r4          )
257 EX(     mov.l   r1,@(4,r4)      )
258 EX(     mov.l   r8,@(8,r4)      )
259 EX(     mov.l   r9,@(12,r4)     )
260 
261 EX(     mov.l   @r5+,r1         )
262 EX(     mov.l   @r5+,r8         )
263 EX(     mov.l   @r5+,r0         )
264         xtrct   r1,r10
265         xtrct   r8,r1
266         xtrct   r0,r8
267         shlr16  r0
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)     )
272         bf/s    2b
273          add    #30,r4
274 #else
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)     )
280         add     #-2,r4
281         xtrct   r8,r0
282         xtrct   r9,r8
283         xtrct   r10,r9
284 EX(     mov.l   r0,@(28,r4)     )
285 EX(     mov.l   r8,@(24,r4)     )
286 EX(     mov.l   r9,@(20,r4)     )
287 
288 EX(     mov.l   @(12,r5),r0     )
289 EX(     mov.l   @(8,r5),r8      )
290         xtrct   r0,r10
291 EX(     mov.l   @(4,r5),r9      )
292         mov.l   r10,@(16,r4)
293 EX(     mov.l   @r5,r10         )
294         xtrct   r8,r0
295         xtrct   r9,r8
296         xtrct   r10,r9
297 EX(     mov.l   r0,@(12,r4)     )
298 EX(     mov.l   r8,@(8,r4)      )
299         swap.w  r10,r0
300 EX(     mov.l   r9,@(4,r4)      )
301 EX(     mov.w   r0,@(2,r4)      )
302 
303         add     #32,r5
304         bf/s    2b
305          add    #34,r4
306 #endif
307         tst     r2,r2
308         bt      .L_cleanup
309 
310 1:      ! Read longword, write two words per iteration
311 EX(     mov.l   @r5+,r0         )
312         dt      r2
313 #ifdef CONFIG_CPU_LITTLE_ENDIAN
314 EX(     mov.w   r0,@r4          )
315         shlr16  r0
316 EX(     mov.w   r0,@(2,r4)      )
317 #else
318 EX(     mov.w   r0,@(2,r4)      )
319         shlr16  r0
320 EX(     mov.w   r0,@r4          )
321 #endif
322         bf/s    1b
323          add    #4,r4
324 
325         bra     .L_cleanup
326          nop
327 
328 ! Destination = 01 or 11
329 
330 .L_dest01:
331 .L_dest11:
332         ! Read longword, write byte, word, byte per iteration
333 EX(     mov.l   @r5+,r0         )
334         dt      r2
335 #ifdef CONFIG_CPU_LITTLE_ENDIAN
336 EX(     mov.b   r0,@r4          )
337         shlr8   r0
338         add     #1,r4
339 EX(     mov.w   r0,@r4          )
340         shlr16  r0
341 EX(     mov.b   r0,@(2,r4)      )
342         bf/s    .L_dest01
343          add    #3,r4
344 #else
345 EX(     mov.b   r0,@(3,r4)      )
346         shlr8   r0
347         swap.w  r0,r7
348 EX(     mov.b   r7,@r4          )
349         add     #1,r4
350 EX(     mov.w   r0,@r4          )
351         bf/s    .L_dest01
352          add    #3,r4
353 #endif
354 
355 ! Cleanup last few bytes
356 .L_cleanup:
357         mov     r6,r0
358         and     #3,r0
359         tst     r0,r0
360         bt      .L_exit
361         mov     r0,r6
362 
363 .L_cleanup_loop:
364 EX(     mov.b   @r5+,r0         )
365         dt      r6
366 EX(     mov.b   r0,@r4          )
367         bf/s    .L_cleanup_loop
368          add    #1,r4
369 
370 .L_exit:
371         mov     #0,r0           ! normal return
372 
373 5000:
374 
375 # Exception handler:
376 .section .fixup, "ax"
377 6000:
378         mov.l   8000f,r1
379         mov     r3,r0
380         jmp     @r1
381          sub    r4,r0
382         .align  2
383 8000:   .long   5000b
384 
385 .previous
386         mov.l   @r15+,r8
387         mov.l   @r15+,r9
388         mov.l   @r15+,r10
389         rts
390          mov.l  @r15+,r11

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php