1/* $Id: copy_page.S,v 1.1.1.1.2.6 2003/03/23 15:30:58 sugioka Exp $ 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 * 8 */ 9#include <linux/linkage.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 + 4096 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.w .L4096,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(__sh3__) 45 mov.l r0,@r10 46#elif defined(__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(__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#if defined(__SH4__) 72/* 73 * __copy_user_page 74 * @to: P1 address (with same color) 75 * @from: P1 address 76 * @orig_to: P1 address 77 * 78 * void __copy_user_page(void *to, void *from, void *orig_to) 79 */ 80 81/* 82 * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch 83 * r8 --- from + 4096 84 * r9 --- orig_to 85 * r10 --- to 86 * r11 --- from 87 */ 88ENTRY(__copy_user_page) 89 mov.l r8,@-r15 90 mov.l r9,@-r15 91 mov.l r10,@-r15 92 mov.l r11,@-r15 93 mov r4,r10 94 mov r5,r11 95 mov r6,r9 96 mov r5,r8 97 mov.w .L4096,r0 98 add r0,r8 99 ! 1001: ocbi @r9 101 add #32,r9 102 mov.l @r11+,r0 103 mov.l @r11+,r1 104 mov.l @r11+,r2 105 mov.l @r11+,r3 106 mov.l @r11+,r4 107 mov.l @r11+,r5 108 mov.l @r11+,r6 109 mov.l @r11+,r7 110 movca.l r0,@r10 111 mov r10,r0 112 add #32,r10 113 mov.l r7,@-r10 114 mov.l r6,@-r10 115 mov.l r5,@-r10 116 mov.l r4,@-r10 117 mov.l r3,@-r10 118 mov.l r2,@-r10 119 mov.l r1,@-r10 120 ocbwb @r0 121 cmp/eq r11,r8 122 bf/s 1b 123 add #28,r10 124 ! 125 mov.l @r15+,r11 126 mov.l @r15+,r10 127 mov.l @r15+,r9 128 mov.l @r15+,r8 129 rts 130 nop 131#endif 132.L4096: .word 4096 133/* 134 * __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); 135 * Return the number of bytes NOT copied 136 */ 137#define EX(...) \ 138 9999: __VA_ARGS__ ; \ 139 .section __ex_table, "a"; \ 140 .long 9999b, 6000f ; \ 141 .previous 142ENTRY(__copy_user) 143 tst r6,r6 ! Check explicitly for zero 144 bf 1f 145 rts 146 mov #0,r0 ! normal return 1471: 148 mov.l r10,@-r15 149 mov.l r9,@-r15 150 mov.l r8,@-r15 151 mov r4,r3 152 add r6,r3 ! last destination address 153 mov #12,r0 ! Check if small number of bytes 154 cmp/gt r0,r6 155 bt 2f 156 bra .L_cleanup_loop 157 nop 1582: 159 neg r5,r0 ! Calculate bytes needed to align source 160 add #4,r0 161 and #3,r0 162 tst r0,r0 163 bt .L_jump 164 mov r0,r1 165 166.L_loop1: 167 ! Copy bytes to align source 168EX( mov.b @r5+,r0 ) 169 dt r1 170EX( mov.b r0,@r4 ) 171 add #-1,r6 172 bf/s .L_loop1 173 add #1,r4 174 175.L_jump: 176 mov r6,r2 ! Calculate number of longwords to copy 177 shlr2 r2 178 tst r2,r2 179 bt .L_cleanup 180 181 mov r4,r0 ! Jump to appropriate routine 182 and #3,r0 183 mov r0,r1 184 shll2 r1 185 mova .L_jump_tbl,r0 186 mov.l @(r0,r1),r1 187 jmp @r1 188 nop 189 190 .align 2 191.L_jump_tbl: 192 .long .L_dest00 193 .long .L_dest01 194 .long .L_dest10 195 .long .L_dest11 196 197! Destination = 00 198 199.L_dest00: 200 mov r2,r7 201 shlr2 r7 202 shlr r7 203 tst r7,r7 204 mov #7,r0 205 bt/s 1f 206 and r0,r2 207 .align 2 2082: 209EX( mov.l @r5+,r0 ) 210EX( mov.l @r5+,r8 ) 211EX( mov.l @r5+,r9 ) 212EX( mov.l @r5+,r10 ) 213EX( mov.l r0,@r4 ) 214EX( mov.l r8,@(4,r4) ) 215EX( mov.l r9,@(8,r4) ) 216EX( mov.l r10,@(12,r4) ) 217EX( mov.l @r5+,r0 ) 218EX( mov.l @r5+,r8 ) 219EX( mov.l @r5+,r9 ) 220EX( mov.l @r5+,r10 ) 221 dt r7 222EX( mov.l r0,@(16,r4) ) 223EX( mov.l r8,@(20,r4) ) 224EX( mov.l r9,@(24,r4) ) 225EX( mov.l r10,@(28,r4) ) 226 bf/s 2b 227 add #32,r4 228 tst r2,r2 229 bt .L_cleanup 2301: 231EX( mov.l @r5+,r0 ) 232 dt r2 233EX( mov.l r0,@r4 ) 234 bf/s 1b 235 add #4,r4 236 237 bra .L_cleanup 238 nop 239 240! Destination = 10 241 242.L_dest10: 243 mov r2,r7 244 shlr2 r7 245 shlr r7 246 tst r7,r7 247 mov #7,r0 248 bt/s 1f 249 and r0,r2 2502: 251 dt r7 252#ifdef __LITTLE_ENDIAN__ 253EX( mov.l @r5+,r0 ) 254EX( mov.l @r5+,r1 ) 255EX( mov.l @r5+,r8 ) 256EX( mov.l @r5+,r9 ) 257EX( mov.l @r5+,r10 ) 258EX( mov.w r0,@r4 ) 259 add #2,r4 260 xtrct r1,r0 261 xtrct r8,r1 262 xtrct r9,r8 263 xtrct r10,r9 264 265EX( mov.l r0,@r4 ) 266EX( mov.l r1,@(4,r4) ) 267EX( mov.l r8,@(8,r4) ) 268EX( mov.l r9,@(12,r4) ) 269 270EX( mov.l @r5+,r1 ) 271EX( mov.l @r5+,r8 ) 272EX( mov.l @r5+,r0 ) 273 xtrct r1,r10 274 xtrct r8,r1 275 xtrct r0,r8 276 shlr16 r0 277EX( mov.l r10,@(16,r4) ) 278EX( mov.l r1,@(20,r4) ) 279EX( mov.l r8,@(24,r4) ) 280EX( mov.w r0,@(28,r4) ) 281 bf/s 2b 282 add #30,r4 283#else 284EX( mov.l @(28,r5),r0 ) 285EX( mov.l @(24,r5),r8 ) 286EX( mov.l @(20,r5),r9 ) 287EX( mov.l @(16,r5),r10 ) 288EX( mov.w r0,@(30,r4) ) 289 add #-2,r4 290 xtrct r8,r0 291 xtrct r9,r8 292 xtrct r10,r9 293EX( mov.l r0,@(28,r4) ) 294EX( mov.l r8,@(24,r4) ) 295EX( mov.l r9,@(20,r4) ) 296 297EX( mov.l @(12,r5),r0 ) 298EX( mov.l @(8,r5),r8 ) 299 xtrct r0,r10 300EX( mov.l @(4,r5),r9 ) 301 mov.l r10,@(16,r4) 302EX( mov.l @r5,r10 ) 303 xtrct r8,r0 304 xtrct r9,r8 305 xtrct r10,r9 306EX( mov.l r0,@(12,r4) ) 307EX( mov.l r8,@(8,r4) ) 308 swap.w r10,r0 309EX( mov.l r9,@(4,r4) ) 310EX( mov.w r0,@(2,r4) ) 311 312 add #32,r5 313 bf/s 2b 314 add #34,r4 315#endif 316 tst r2,r2 317 bt .L_cleanup 318 3191: ! Read longword, write two words per iteration 320EX( mov.l @r5+,r0 ) 321 dt r2 322#ifdef __LITTLE_ENDIAN__ 323EX( mov.w r0,@r4 ) 324 shlr16 r0 325EX( mov.w r0,@(2,r4) ) 326#else 327EX( mov.w r0,@(2,r4) ) 328 shlr16 r0 329EX( mov.w r0,@r4 ) 330#endif 331 bf/s 1b 332 add #4,r4 333 334 bra .L_cleanup 335 nop 336 337! Destination = 01 or 11 338 339.L_dest01: 340.L_dest11: 341 ! Read longword, write byte, word, byte per iteration 342EX( mov.l @r5+,r0 ) 343 dt r2 344#ifdef __LITTLE_ENDIAN__ 345EX( mov.b r0,@r4 ) 346 shlr8 r0 347 add #1,r4 348EX( mov.w r0,@r4 ) 349 shlr16 r0 350EX( mov.b r0,@(2,r4) ) 351 bf/s .L_dest01 352 add #3,r4 353#else 354EX( mov.b r0,@(3,r4) ) 355 shlr8 r0 356 swap.w r0,r7 357EX( mov.b r7,@r4 ) 358 add #1,r4 359EX( mov.w r0,@r4 ) 360 bf/s .L_dest01 361 add #3,r4 362#endif 363 364! Cleanup last few bytes 365.L_cleanup: 366 mov r6,r0 367 and #3,r0 368 tst r0,r0 369 bt .L_exit 370 mov r0,r6 371 372.L_cleanup_loop: 373EX( mov.b @r5+,r0 ) 374 dt r6 375EX( mov.b r0,@r4 ) 376 bf/s .L_cleanup_loop 377 add #1,r4 378 379.L_exit: 380 mov #0,r0 ! normal return 3815000: 382 383# Exception handler: 384.section .fixup, "ax" 3856000: 386 mov.l 8000f,r1 387 mov r3,r0 388 jmp @r1 389 sub r4,r0 390 .align 2 3918000: .long 5000b 392 393.previous 394 mov.l @r15+,r8 395 mov.l @r15+,r9 396 rts 397 mov.l @r15+,r10 398