root/arch/sh/lib/copy_page.S

/* [<][>][^][v][top][bottom][index][help] */
   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

/* [<][>][^][v][top][bottom][index][help] */