Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sparc32: switch copy_user.S away from range exception table entries

Those were the last range exception table entries, which will allow
to get rid of a lot of weirdness. Emits the same code into .text.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro c4da8e0d cfd5fa70

+110 -201
+110 -201
arch/sparc/lib/copy_user.S
··· 21 21 /* Work around cpp -rob */ 22 22 #define ALLOC #alloc 23 23 #define EXECINSTR #execinstr 24 + 25 + #define EX_ENTRY(l1, l2) \ 26 + .section __ex_table,ALLOC; \ 27 + .align 4; \ 28 + .word l1, l2; \ 29 + .text; 30 + 24 31 #define EX(x,y,a,b) \ 25 32 98: x,y; \ 26 33 .section .fixup,ALLOC,EXECINSTR; \ 27 34 .align 4; \ 28 - 99: ba fixupretl; \ 29 - a, b, %g3; \ 30 - .section __ex_table,ALLOC; \ 31 - .align 4; \ 32 - .word 98b, 99b; \ 33 - .text; \ 34 - .align 4 35 + 99: retl; \ 36 + a, b, %o0; \ 37 + EX_ENTRY(98b, 99b) 35 38 36 39 #define EX2(x,y,c,d,e,a,b) \ 37 40 98: x,y; \ 38 41 .section .fixup,ALLOC,EXECINSTR; \ 39 42 .align 4; \ 40 43 99: c, d, e; \ 41 - ba fixupretl; \ 42 - a, b, %g3; \ 43 - .section __ex_table,ALLOC; \ 44 - .align 4; \ 45 - .word 98b, 99b; \ 46 - .text; \ 47 - .align 4 44 + retl; \ 45 + a, b, %o0; \ 46 + EX_ENTRY(98b, 99b) 48 47 49 48 #define EXO2(x,y) \ 50 49 98: x, y; \ 51 - .section __ex_table,ALLOC; \ 52 - .align 4; \ 53 - .word 98b, 97f; \ 54 - .text; \ 55 - .align 4 50 + EX_ENTRY(98b, 97f) 56 51 57 - #define EXT(start,end,handler) \ 58 - .section __ex_table,ALLOC; \ 59 - .align 4; \ 60 - .word start, 0, end, handler; \ 61 - .text; \ 62 - .align 4 52 + #define LD(insn, src, offset, reg, label) \ 53 + 98: insn [%src + (offset)], %reg; \ 54 + .section .fixup,ALLOC,EXECINSTR; \ 55 + 99: ba label; \ 56 + mov offset, %g5; \ 57 + EX_ENTRY(98b, 99b) 63 58 64 - /* Please do not change following macros unless you change logic used 65 - * in .fixup at the end of this file as well 66 - */ 59 + #define ST(insn, dst, offset, reg, label) \ 60 + 98: insn %reg, [%dst + (offset)]; \ 61 + .section .fixup,ALLOC,EXECINSTR; \ 62 + 99: ba label; \ 63 + mov offset, %g5; \ 64 + EX_ENTRY(98b, 99b) 67 65 68 66 /* Both these macros have to start with exactly the same insn */ 67 + /* left: g7 + (g1 % 128) - offset */ 69 68 #define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ 70 - ldd [%src + (offset) + 0x00], %t0; \ 71 - ldd [%src + (offset) + 0x08], %t2; \ 72 - ldd [%src + (offset) + 0x10], %t4; \ 73 - ldd [%src + (offset) + 0x18], %t6; \ 74 - st %t0, [%dst + (offset) + 0x00]; \ 75 - st %t1, [%dst + (offset) + 0x04]; \ 76 - st %t2, [%dst + (offset) + 0x08]; \ 77 - st %t3, [%dst + (offset) + 0x0c]; \ 78 - st %t4, [%dst + (offset) + 0x10]; \ 79 - st %t5, [%dst + (offset) + 0x14]; \ 80 - st %t6, [%dst + (offset) + 0x18]; \ 81 - st %t7, [%dst + (offset) + 0x1c]; 69 + LD(ldd, src, offset + 0x00, t0, bigchunk_fault) \ 70 + LD(ldd, src, offset + 0x08, t2, bigchunk_fault) \ 71 + LD(ldd, src, offset + 0x10, t4, bigchunk_fault) \ 72 + LD(ldd, src, offset + 0x18, t6, bigchunk_fault) \ 73 + ST(st, dst, offset + 0x00, t0, bigchunk_fault) \ 74 + ST(st, dst, offset + 0x04, t1, bigchunk_fault) \ 75 + ST(st, dst, offset + 0x08, t2, bigchunk_fault) \ 76 + ST(st, dst, offset + 0x0c, t3, bigchunk_fault) \ 77 + ST(st, dst, offset + 0x10, t4, bigchunk_fault) \ 78 + ST(st, dst, offset + 0x14, t5, bigchunk_fault) \ 79 + ST(st, dst, offset + 0x18, t6, bigchunk_fault) \ 80 + ST(st, dst, offset + 0x1c, t7, bigchunk_fault) 82 81 82 + /* left: g7 + (g1 % 128) - offset */ 83 83 #define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ 84 - ldd [%src + (offset) + 0x00], %t0; \ 85 - ldd [%src + (offset) + 0x08], %t2; \ 86 - ldd [%src + (offset) + 0x10], %t4; \ 87 - ldd [%src + (offset) + 0x18], %t6; \ 88 - std %t0, [%dst + (offset) + 0x00]; \ 89 - std %t2, [%dst + (offset) + 0x08]; \ 90 - std %t4, [%dst + (offset) + 0x10]; \ 91 - std %t6, [%dst + (offset) + 0x18]; 84 + LD(ldd, src, offset + 0x00, t0, bigchunk_fault) \ 85 + LD(ldd, src, offset + 0x08, t2, bigchunk_fault) \ 86 + LD(ldd, src, offset + 0x10, t4, bigchunk_fault) \ 87 + LD(ldd, src, offset + 0x18, t6, bigchunk_fault) \ 88 + ST(std, dst, offset + 0x00, t0, bigchunk_fault) \ 89 + ST(std, dst, offset + 0x08, t2, bigchunk_fault) \ 90 + ST(std, dst, offset + 0x10, t4, bigchunk_fault) \ 91 + ST(std, dst, offset + 0x18, t6, bigchunk_fault) 92 92 93 + .section .fixup,#alloc,#execinstr 94 + bigchunk_fault: 95 + sub %g7, %g5, %o0 96 + and %g1, 127, %g1 97 + retl 98 + add %o0, %g1, %o0 99 + 100 + /* left: offset + 16 + (g1 % 16) */ 93 101 #define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ 94 - ldd [%src - (offset) - 0x10], %t0; \ 95 - ldd [%src - (offset) - 0x08], %t2; \ 96 - st %t0, [%dst - (offset) - 0x10]; \ 97 - st %t1, [%dst - (offset) - 0x0c]; \ 98 - st %t2, [%dst - (offset) - 0x08]; \ 99 - st %t3, [%dst - (offset) - 0x04]; 102 + LD(ldd, src, -(offset + 0x10), t0, lastchunk_fault) \ 103 + LD(ldd, src, -(offset + 0x08), t2, lastchunk_fault) \ 104 + ST(st, dst, -(offset + 0x10), t0, lastchunk_fault) \ 105 + ST(st, dst, -(offset + 0x0c), t1, lastchunk_fault) \ 106 + ST(st, dst, -(offset + 0x08), t2, lastchunk_fault) \ 107 + ST(st, dst, -(offset + 0x04), t3, lastchunk_fault) 100 108 109 + .section .fixup,#alloc,#execinstr 110 + lastchunk_fault: 111 + and %g1, 15, %g1 112 + retl 113 + sub %g1, %g5, %o0 114 + 115 + /* left: o3 + (o2 % 16) - offset */ 101 116 #define MOVE_HALFCHUNK(src, dst, offset, t0, t1, t2, t3) \ 102 - lduh [%src + (offset) + 0x00], %t0; \ 103 - lduh [%src + (offset) + 0x02], %t1; \ 104 - lduh [%src + (offset) + 0x04], %t2; \ 105 - lduh [%src + (offset) + 0x06], %t3; \ 106 - sth %t0, [%dst + (offset) + 0x00]; \ 107 - sth %t1, [%dst + (offset) + 0x02]; \ 108 - sth %t2, [%dst + (offset) + 0x04]; \ 109 - sth %t3, [%dst + (offset) + 0x06]; 117 + LD(lduh, src, offset + 0x00, t0, halfchunk_fault) \ 118 + LD(lduh, src, offset + 0x02, t1, halfchunk_fault) \ 119 + LD(lduh, src, offset + 0x04, t2, halfchunk_fault) \ 120 + LD(lduh, src, offset + 0x06, t3, halfchunk_fault) \ 121 + ST(sth, dst, offset + 0x00, t0, halfchunk_fault) \ 122 + ST(sth, dst, offset + 0x02, t1, halfchunk_fault) \ 123 + ST(sth, dst, offset + 0x04, t2, halfchunk_fault) \ 124 + ST(sth, dst, offset + 0x06, t3, halfchunk_fault) 110 125 126 + /* left: o3 + (o2 % 16) + offset + 2 */ 111 127 #define MOVE_SHORTCHUNK(src, dst, offset, t0, t1) \ 112 - ldub [%src - (offset) - 0x02], %t0; \ 113 - ldub [%src - (offset) - 0x01], %t1; \ 114 - stb %t0, [%dst - (offset) - 0x02]; \ 115 - stb %t1, [%dst - (offset) - 0x01]; 128 + LD(ldub, src, -(offset + 0x02), t0, halfchunk_fault) \ 129 + LD(ldub, src, -(offset + 0x01), t1, halfchunk_fault) \ 130 + ST(stb, dst, -(offset + 0x02), t0, halfchunk_fault) \ 131 + ST(stb, dst, -(offset + 0x01), t1, halfchunk_fault) 132 + 133 + .section .fixup,#alloc,#execinstr 134 + halfchunk_fault: 135 + and %o2, 15, %o2 136 + sub %o3, %g5, %o3 137 + retl 138 + add %o2, %o3, %o0 139 + 140 + /* left: offset + 2 + (o2 % 2) */ 141 + #define MOVE_LAST_SHORTCHUNK(src, dst, offset, t0, t1) \ 142 + LD(ldub, src, -(offset + 0x02), t0, last_shortchunk_fault) \ 143 + LD(ldub, src, -(offset + 0x01), t1, last_shortchunk_fault) \ 144 + ST(stb, dst, -(offset + 0x02), t0, last_shortchunk_fault) \ 145 + ST(stb, dst, -(offset + 0x01), t1, last_shortchunk_fault) 146 + 147 + .section .fixup,#alloc,#execinstr 148 + last_shortchunk_fault: 149 + and %o2, 1, %o2 150 + retl 151 + sub %o2, %g5, %o0 116 152 117 153 .text 118 154 .align 4 ··· 218 182 MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5) 219 183 MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5) 220 184 MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5) 221 - 80: 222 - EXT(5b, 80b, 50f) 223 185 subcc %g7, 128, %g7 224 186 add %o1, 128, %o1 225 187 bne 5b ··· 235 201 jmpl %o5 + %lo(copy_user_table_end), %g0 236 202 add %o0, %g7, %o0 237 203 238 - copy_user_table: 239 204 MOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5) 240 205 MOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5) 241 206 MOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5) ··· 243 210 MOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5) 244 211 MOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5) 245 212 copy_user_table_end: 246 - EXT(copy_user_table, copy_user_table_end, 51f) 247 213 be copy_user_last7 248 214 andcc %g1, 4, %g0 249 215 ··· 282 250 MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5) 283 251 MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5) 284 252 MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5) 285 - 81: 286 - EXT(ldd_std, 81b, 52f) 287 253 subcc %g7, 128, %g7 288 254 add %o1, 128, %o1 289 255 bne ldd_std ··· 320 290 10: 321 291 MOVE_HALFCHUNK(o1, o0, 0x00, g2, g3, g4, g5) 322 292 MOVE_HALFCHUNK(o1, o0, 0x08, g2, g3, g4, g5) 323 - 82: 324 - EXT(10b, 82b, 53f) 325 293 subcc %o3, 0x10, %o3 326 294 add %o1, 0x10, %o1 327 295 bne 10b ··· 336 308 MOVE_SHORTCHUNK(o1, o0, -0x0c, g2, g3) 337 309 MOVE_SHORTCHUNK(o1, o0, -0x0e, g2, g3) 338 310 MOVE_SHORTCHUNK(o1, o0, -0x10, g2, g3) 339 - 83: 340 - EXT(byte_chunk, 83b, 54f) 341 311 subcc %o3, 0x10, %o3 342 312 add %o1, 0x10, %o1 343 313 bne byte_chunk ··· 351 325 add %o1, %o3, %o1 352 326 jmpl %o5 + %lo(short_table_end), %g0 353 327 andcc %o2, 1, %g0 354 - 84: 355 - MOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3) 356 - MOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3) 357 - MOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3) 358 - MOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3) 359 - MOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3) 360 - MOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3) 361 - MOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3) 328 + MOVE_LAST_SHORTCHUNK(o1, o0, 0x0c, g2, g3) 329 + MOVE_LAST_SHORTCHUNK(o1, o0, 0x0a, g2, g3) 330 + MOVE_LAST_SHORTCHUNK(o1, o0, 0x08, g2, g3) 331 + MOVE_LAST_SHORTCHUNK(o1, o0, 0x06, g2, g3) 332 + MOVE_LAST_SHORTCHUNK(o1, o0, 0x04, g2, g3) 333 + MOVE_LAST_SHORTCHUNK(o1, o0, 0x02, g2, g3) 334 + MOVE_LAST_SHORTCHUNK(o1, o0, 0x00, g2, g3) 362 335 short_table_end: 363 - EXT(84b, short_table_end, 55f) 364 336 be 1f 365 337 nop 366 338 EX(ldub [%o1], %g2, add %g0, 1) ··· 387 363 .section .fixup,#alloc,#execinstr 388 364 .align 4 389 365 97: 390 - mov %o2, %g3 391 - fixupretl: 392 366 retl 393 - mov %g3, %o0 394 - 395 - /* exception routine sets %g2 to (broken_insn - first_insn)>>2 */ 396 - 50: 397 - /* This magic counts how many bytes are left when crash in MOVE_BIGCHUNK 398 - * happens. This is derived from the amount ldd reads, st stores, etc. 399 - * x = g2 % 12; 400 - * g3 = g1 + g7 - ((g2 / 12) * 32 + (x < 4) ? 0 : (x - 4) * 4); 401 - * o0 += (g2 / 12) * 32; 402 - */ 403 - cmp %g2, 12 404 - add %o0, %g7, %o0 405 - bcs 1f 406 - cmp %g2, 24 407 - bcs 2f 408 - cmp %g2, 36 409 - bcs 3f 410 - nop 411 - sub %g2, 12, %g2 412 - sub %g7, 32, %g7 413 - 3: sub %g2, 12, %g2 414 - sub %g7, 32, %g7 415 - 2: sub %g2, 12, %g2 416 - sub %g7, 32, %g7 417 - 1: cmp %g2, 4 418 - bcs,a 60f 419 - clr %g2 420 - sub %g2, 4, %g2 421 - sll %g2, 2, %g2 422 - 60: and %g1, 0x7f, %g3 423 - sub %o0, %g7, %o0 424 - add %g3, %g7, %g3 425 - ba fixupretl 426 - sub %g3, %g2, %g3 427 - 51: 428 - /* i = 41 - g2; j = i % 6; 429 - * g3 = (g1 & 15) + (i / 6) * 16 + (j < 4) ? (j + 1) * 4 : 16; 430 - * o0 -= (i / 6) * 16 + 16; 431 - */ 432 - neg %g2 433 - and %g1, 0xf, %g1 434 - add %g2, 41, %g2 435 - add %o0, %g1, %o0 436 - 1: cmp %g2, 6 437 - bcs,a 2f 438 - cmp %g2, 4 439 - add %g1, 16, %g1 440 - b 1b 441 - sub %g2, 6, %g2 442 - 2: bcc,a 2f 443 - mov 16, %g2 444 - inc %g2 445 - sll %g2, 2, %g2 446 - 2: add %g1, %g2, %g3 447 - ba fixupretl 448 - sub %o0, %g3, %o0 449 - 52: 450 - /* g3 = g1 + g7 - (g2 / 8) * 32 + (g2 & 4) ? (g2 & 3) * 8 : 0; 451 - o0 += (g2 / 8) * 32 */ 452 - andn %g2, 7, %g4 453 - add %o0, %g7, %o0 454 - andcc %g2, 4, %g0 455 - and %g2, 3, %g2 456 - sll %g4, 2, %g4 457 - sll %g2, 3, %g2 458 - bne 60b 459 - sub %g7, %g4, %g7 460 - ba 60b 461 - clr %g2 462 - 53: 463 - /* g3 = o3 + (o2 & 15) - (g2 & 8) - (g2 & 4) ? (g2 & 3) * 2 : 0; 464 - o0 += (g2 & 8) */ 465 - and %g2, 3, %g4 466 - andcc %g2, 4, %g0 467 - and %g2, 8, %g2 468 - sll %g4, 1, %g4 469 - be 1f 470 - add %o0, %g2, %o0 471 - add %g2, %g4, %g2 472 - 1: and %o2, 0xf, %g3 473 - add %g3, %o3, %g3 474 - ba fixupretl 475 - sub %g3, %g2, %g3 476 - 54: 477 - /* g3 = o3 + (o2 & 15) - (g2 / 4) * 2 - (g2 & 2) ? (g2 & 1) : 0; 478 - o0 += (g2 / 4) * 2 */ 479 - srl %g2, 2, %o4 480 - and %g2, 1, %o5 481 - srl %g2, 1, %g2 482 - add %o4, %o4, %o4 483 - and %o5, %g2, %o5 484 - and %o2, 0xf, %o2 485 - add %o0, %o4, %o0 486 - sub %o3, %o5, %o3 487 - sub %o2, %o4, %o2 488 - ba fixupretl 489 - add %o2, %o3, %g3 490 - 55: 491 - /* i = 27 - g2; 492 - g3 = (o2 & 1) + i / 4 * 2 + !(i & 3); 493 - o0 -= i / 4 * 2 + 1 */ 494 - neg %g2 495 - and %o2, 1, %o2 496 - add %g2, 27, %g2 497 - srl %g2, 2, %o5 498 - andcc %g2, 3, %g0 499 - mov 1, %g2 500 - add %o5, %o5, %o5 501 - be,a 1f 502 - clr %g2 503 - 1: add %g2, %o5, %g3 504 - sub %o0, %g3, %o0 505 - ba fixupretl 506 - add %g3, %o2, %g3 367 + mov %o2, %o0 507 368 508 369 .globl __copy_user_end 509 370 __copy_user_end: