diff options
author | Markos Chandras <markos.chandras@imgtec.com> | 2014-01-07 07:57:04 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-03-26 18:09:14 -0400 |
commit | 5bc05971d353cd10bce5044a1ef60b9d5b504810 (patch) | |
tree | 4368ca5ba8281a2c23692d456bacbd14f5888e67 /arch/mips | |
parent | b3c3025b2c5536c2b243f4947cffe58628758020 (diff) |
MIPS: lib: memcpy: Merge EXC and load/store macros
Each load/store macro always adds an entry to the __ex_table
using the EXC macro. Therefore, these load/store macros are now merged
with the EXC one. The argument list is also expanded in order to make
the macro more flexible. The extra 'type' argument is not used by this
commit, but it will be used when the EVA support is added to the memcpy.
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/lib/memcpy.S | 158 |
1 files changed, 89 insertions, 69 deletions
diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S index c5c40dad0bbf..ab9f04641640 100644 --- a/arch/mips/lib/memcpy.S +++ b/arch/mips/lib/memcpy.S | |||
@@ -10,6 +10,7 @@ | |||
10 | * Copyright (C) 2002 Broadcom, Inc. | 10 | * Copyright (C) 2002 Broadcom, Inc. |
11 | * memcpy/copy_user author: Mark Vandevoorde | 11 | * memcpy/copy_user author: Mark Vandevoorde |
12 | * Copyright (C) 2007 Maciej W. Rozycki | 12 | * Copyright (C) 2007 Maciej W. Rozycki |
13 | * Copyright (C) 2014 Imagination Technologies Ltd. | ||
13 | * | 14 | * |
14 | * Mnemonic names for arguments to memcpy/__copy_user | 15 | * Mnemonic names for arguments to memcpy/__copy_user |
15 | */ | 16 | */ |
@@ -85,8 +86,22 @@ | |||
85 | * they're not protected. | 86 | * they're not protected. |
86 | */ | 87 | */ |
87 | 88 | ||
88 | #define EXC(inst_reg,addr,handler) \ | 89 | /* Instruction type */ |
89 | 9: inst_reg, addr; \ | 90 | #define LD_INSN 1 |
91 | #define ST_INSN 2 | ||
92 | |||
93 | /* | ||
94 | * Wrapper to add an entry in the exception table | ||
95 | * in case the insn causes a memory exception. | ||
96 | * Arguments: | ||
97 | * insn : Load/store instruction | ||
98 | * type : Instruction type | ||
99 | * reg : Register | ||
100 | * addr : Address | ||
101 | * handler : Exception handler | ||
102 | */ | ||
103 | #define EXC(insn, type, reg, addr, handler) \ | ||
104 | 9: insn reg, addr; \ | ||
90 | .section __ex_table,"a"; \ | 105 | .section __ex_table,"a"; \ |
91 | PTR 9b, handler; \ | 106 | PTR 9b, handler; \ |
92 | .previous | 107 | .previous |
@@ -100,12 +115,13 @@ | |||
100 | 115 | ||
101 | #ifdef USE_DOUBLE | 116 | #ifdef USE_DOUBLE |
102 | 117 | ||
103 | #define LOAD ld | 118 | #define LOADK ld /* No exception */ |
104 | #define LOADL ldl | 119 | #define LOAD(reg, addr, handler) EXC(ld, LD_INSN, reg, addr, handler) |
105 | #define LOADR ldr | 120 | #define LOADL(reg, addr, handler) EXC(ldl, LD_INSN, reg, addr, handler) |
106 | #define STOREL sdl | 121 | #define LOADR(reg, addr, handler) EXC(ldr, LD_INSN, reg, addr, handler) |
107 | #define STORER sdr | 122 | #define STOREL(reg, addr, handler) EXC(sdl, ST_INSN, reg, addr, handler) |
108 | #define STORE sd | 123 | #define STORER(reg, addr, handler) EXC(sdr, ST_INSN, reg, addr, handler) |
124 | #define STORE(reg, addr, handler) EXC(sd, ST_INSN, reg, addr, handler) | ||
109 | #define ADD daddu | 125 | #define ADD daddu |
110 | #define SUB dsubu | 126 | #define SUB dsubu |
111 | #define SRL dsrl | 127 | #define SRL dsrl |
@@ -136,12 +152,13 @@ | |||
136 | 152 | ||
137 | #else | 153 | #else |
138 | 154 | ||
139 | #define LOAD lw | 155 | #define LOADK lw /* No exception */ |
140 | #define LOADL lwl | 156 | #define LOAD(reg, addr, handler) EXC(lw, LD_INSN, reg, addr, handler) |
141 | #define LOADR lwr | 157 | #define LOADL(reg, addr, handler) EXC(lwl, LD_INSN, reg, addr, handler) |
142 | #define STOREL swl | 158 | #define LOADR(reg, addr, handler) EXC(lwr, LD_INSN, reg, addr, handler) |
143 | #define STORER swr | 159 | #define STOREL(reg, addr, handler) EXC(swl, ST_INSN, reg, addr, handler) |
144 | #define STORE sw | 160 | #define STORER(reg, addr, handler) EXC(swr, ST_INSN, reg, addr, handler) |
161 | #define STORE(reg, addr, handler) EXC(sw, ST_INSN, reg, addr, handler) | ||
145 | #define ADD addu | 162 | #define ADD addu |
146 | #define SUB subu | 163 | #define SUB subu |
147 | #define SRL srl | 164 | #define SRL srl |
@@ -154,6 +171,9 @@ | |||
154 | 171 | ||
155 | #endif /* USE_DOUBLE */ | 172 | #endif /* USE_DOUBLE */ |
156 | 173 | ||
174 | #define LOADB(reg, addr, handler) EXC(lb, LD_INSN, reg, addr, handler) | ||
175 | #define STOREB(reg, addr, handler) EXC(sb, ST_INSN, reg, addr, handler) | ||
176 | |||
157 | #ifdef CONFIG_CPU_LITTLE_ENDIAN | 177 | #ifdef CONFIG_CPU_LITTLE_ENDIAN |
158 | #define LDFIRST LOADR | 178 | #define LDFIRST LOADR |
159 | #define LDREST LOADL | 179 | #define LDREST LOADL |
@@ -243,25 +263,25 @@ __copy_user_common: | |||
243 | .align 4 | 263 | .align 4 |
244 | 1: | 264 | 1: |
245 | R10KCBARRIER(0(ra)) | 265 | R10KCBARRIER(0(ra)) |
246 | EXC( LOAD t0, UNIT(0)(src), .Ll_exc) | 266 | LOAD(t0, UNIT(0)(src), .Ll_exc) |
247 | EXC( LOAD t1, UNIT(1)(src), .Ll_exc_copy) | 267 | LOAD(t1, UNIT(1)(src), .Ll_exc_copy) |
248 | EXC( LOAD t2, UNIT(2)(src), .Ll_exc_copy) | 268 | LOAD(t2, UNIT(2)(src), .Ll_exc_copy) |
249 | EXC( LOAD t3, UNIT(3)(src), .Ll_exc_copy) | 269 | LOAD(t3, UNIT(3)(src), .Ll_exc_copy) |
250 | SUB len, len, 8*NBYTES | 270 | SUB len, len, 8*NBYTES |
251 | EXC( LOAD t4, UNIT(4)(src), .Ll_exc_copy) | 271 | LOAD(t4, UNIT(4)(src), .Ll_exc_copy) |
252 | EXC( LOAD t7, UNIT(5)(src), .Ll_exc_copy) | 272 | LOAD(t7, UNIT(5)(src), .Ll_exc_copy) |
253 | EXC( STORE t0, UNIT(0)(dst), .Ls_exc_p8u) | 273 | STORE(t0, UNIT(0)(dst), .Ls_exc_p8u) |
254 | EXC( STORE t1, UNIT(1)(dst), .Ls_exc_p7u) | 274 | STORE(t1, UNIT(1)(dst), .Ls_exc_p7u) |
255 | EXC( LOAD t0, UNIT(6)(src), .Ll_exc_copy) | 275 | LOAD(t0, UNIT(6)(src), .Ll_exc_copy) |
256 | EXC( LOAD t1, UNIT(7)(src), .Ll_exc_copy) | 276 | LOAD(t1, UNIT(7)(src), .Ll_exc_copy) |
257 | ADD src, src, 8*NBYTES | 277 | ADD src, src, 8*NBYTES |
258 | ADD dst, dst, 8*NBYTES | 278 | ADD dst, dst, 8*NBYTES |
259 | EXC( STORE t2, UNIT(-6)(dst), .Ls_exc_p6u) | 279 | STORE(t2, UNIT(-6)(dst), .Ls_exc_p6u) |
260 | EXC( STORE t3, UNIT(-5)(dst), .Ls_exc_p5u) | 280 | STORE(t3, UNIT(-5)(dst), .Ls_exc_p5u) |
261 | EXC( STORE t4, UNIT(-4)(dst), .Ls_exc_p4u) | 281 | STORE(t4, UNIT(-4)(dst), .Ls_exc_p4u) |
262 | EXC( STORE t7, UNIT(-3)(dst), .Ls_exc_p3u) | 282 | STORE(t7, UNIT(-3)(dst), .Ls_exc_p3u) |
263 | EXC( STORE t0, UNIT(-2)(dst), .Ls_exc_p2u) | 283 | STORE(t0, UNIT(-2)(dst), .Ls_exc_p2u) |
264 | EXC( STORE t1, UNIT(-1)(dst), .Ls_exc_p1u) | 284 | STORE(t1, UNIT(-1)(dst), .Ls_exc_p1u) |
265 | PREF( 0, 8*32(src) ) | 285 | PREF( 0, 8*32(src) ) |
266 | PREF( 1, 8*32(dst) ) | 286 | PREF( 1, 8*32(dst) ) |
267 | bne len, rem, 1b | 287 | bne len, rem, 1b |
@@ -278,17 +298,17 @@ EXC( STORE t1, UNIT(-1)(dst), .Ls_exc_p1u) | |||
278 | /* | 298 | /* |
279 | * len >= 4*NBYTES | 299 | * len >= 4*NBYTES |
280 | */ | 300 | */ |
281 | EXC( LOAD t0, UNIT(0)(src), .Ll_exc) | 301 | LOAD( t0, UNIT(0)(src), .Ll_exc) |
282 | EXC( LOAD t1, UNIT(1)(src), .Ll_exc_copy) | 302 | LOAD( t1, UNIT(1)(src), .Ll_exc_copy) |
283 | EXC( LOAD t2, UNIT(2)(src), .Ll_exc_copy) | 303 | LOAD( t2, UNIT(2)(src), .Ll_exc_copy) |
284 | EXC( LOAD t3, UNIT(3)(src), .Ll_exc_copy) | 304 | LOAD( t3, UNIT(3)(src), .Ll_exc_copy) |
285 | SUB len, len, 4*NBYTES | 305 | SUB len, len, 4*NBYTES |
286 | ADD src, src, 4*NBYTES | 306 | ADD src, src, 4*NBYTES |
287 | R10KCBARRIER(0(ra)) | 307 | R10KCBARRIER(0(ra)) |
288 | EXC( STORE t0, UNIT(0)(dst), .Ls_exc_p4u) | 308 | STORE(t0, UNIT(0)(dst), .Ls_exc_p4u) |
289 | EXC( STORE t1, UNIT(1)(dst), .Ls_exc_p3u) | 309 | STORE(t1, UNIT(1)(dst), .Ls_exc_p3u) |
290 | EXC( STORE t2, UNIT(2)(dst), .Ls_exc_p2u) | 310 | STORE(t2, UNIT(2)(dst), .Ls_exc_p2u) |
291 | EXC( STORE t3, UNIT(3)(dst), .Ls_exc_p1u) | 311 | STORE(t3, UNIT(3)(dst), .Ls_exc_p1u) |
292 | .set reorder /* DADDI_WAR */ | 312 | .set reorder /* DADDI_WAR */ |
293 | ADD dst, dst, 4*NBYTES | 313 | ADD dst, dst, 4*NBYTES |
294 | beqz len, .Ldone | 314 | beqz len, .Ldone |
@@ -301,10 +321,10 @@ EXC( STORE t3, UNIT(3)(dst), .Ls_exc_p1u) | |||
301 | nop | 321 | nop |
302 | 1: | 322 | 1: |
303 | R10KCBARRIER(0(ra)) | 323 | R10KCBARRIER(0(ra)) |
304 | EXC( LOAD t0, 0(src), .Ll_exc) | 324 | LOAD(t0, 0(src), .Ll_exc) |
305 | ADD src, src, NBYTES | 325 | ADD src, src, NBYTES |
306 | SUB len, len, NBYTES | 326 | SUB len, len, NBYTES |
307 | EXC( STORE t0, 0(dst), .Ls_exc_p1u) | 327 | STORE(t0, 0(dst), .Ls_exc_p1u) |
308 | .set reorder /* DADDI_WAR */ | 328 | .set reorder /* DADDI_WAR */ |
309 | ADD dst, dst, NBYTES | 329 | ADD dst, dst, NBYTES |
310 | bne rem, len, 1b | 330 | bne rem, len, 1b |
@@ -326,10 +346,10 @@ EXC( STORE t0, 0(dst), .Ls_exc_p1u) | |||
326 | ADD t1, dst, len # t1 is just past last byte of dst | 346 | ADD t1, dst, len # t1 is just past last byte of dst |
327 | li bits, 8*NBYTES | 347 | li bits, 8*NBYTES |
328 | SLL rem, len, 3 # rem = number of bits to keep | 348 | SLL rem, len, 3 # rem = number of bits to keep |
329 | EXC( LOAD t0, 0(src), .Ll_exc) | 349 | LOAD(t0, 0(src), .Ll_exc) |
330 | SUB bits, bits, rem # bits = number of bits to discard | 350 | SUB bits, bits, rem # bits = number of bits to discard |
331 | SHIFT_DISCARD t0, t0, bits | 351 | SHIFT_DISCARD t0, t0, bits |
332 | EXC( STREST t0, -1(t1), .Ls_exc) | 352 | STREST(t0, -1(t1), .Ls_exc) |
333 | jr ra | 353 | jr ra |
334 | move len, zero | 354 | move len, zero |
335 | .Ldst_unaligned: | 355 | .Ldst_unaligned: |
@@ -343,13 +363,13 @@ EXC( STREST t0, -1(t1), .Ls_exc) | |||
343 | * Set match = (src and dst have same alignment) | 363 | * Set match = (src and dst have same alignment) |
344 | */ | 364 | */ |
345 | #define match rem | 365 | #define match rem |
346 | EXC( LDFIRST t3, FIRST(0)(src), .Ll_exc) | 366 | LDFIRST(t3, FIRST(0)(src), .Ll_exc) |
347 | ADD t2, zero, NBYTES | 367 | ADD t2, zero, NBYTES |
348 | EXC( LDREST t3, REST(0)(src), .Ll_exc_copy) | 368 | LDREST(t3, REST(0)(src), .Ll_exc_copy) |
349 | SUB t2, t2, t1 # t2 = number of bytes copied | 369 | SUB t2, t2, t1 # t2 = number of bytes copied |
350 | xor match, t0, t1 | 370 | xor match, t0, t1 |
351 | R10KCBARRIER(0(ra)) | 371 | R10KCBARRIER(0(ra)) |
352 | EXC( STFIRST t3, FIRST(0)(dst), .Ls_exc) | 372 | STFIRST(t3, FIRST(0)(dst), .Ls_exc) |
353 | beq len, t2, .Ldone | 373 | beq len, t2, .Ldone |
354 | SUB len, len, t2 | 374 | SUB len, len, t2 |
355 | ADD dst, dst, t2 | 375 | ADD dst, dst, t2 |
@@ -370,24 +390,24 @@ EXC( STFIRST t3, FIRST(0)(dst), .Ls_exc) | |||
370 | * are to the same unit (unless src is aligned, but it's not). | 390 | * are to the same unit (unless src is aligned, but it's not). |
371 | */ | 391 | */ |
372 | R10KCBARRIER(0(ra)) | 392 | R10KCBARRIER(0(ra)) |
373 | EXC( LDFIRST t0, FIRST(0)(src), .Ll_exc) | 393 | LDFIRST(t0, FIRST(0)(src), .Ll_exc) |
374 | EXC( LDFIRST t1, FIRST(1)(src), .Ll_exc_copy) | 394 | LDFIRST(t1, FIRST(1)(src), .Ll_exc_copy) |
375 | SUB len, len, 4*NBYTES | 395 | SUB len, len, 4*NBYTES |
376 | EXC( LDREST t0, REST(0)(src), .Ll_exc_copy) | 396 | LDREST(t0, REST(0)(src), .Ll_exc_copy) |
377 | EXC( LDREST t1, REST(1)(src), .Ll_exc_copy) | 397 | LDREST(t1, REST(1)(src), .Ll_exc_copy) |
378 | EXC( LDFIRST t2, FIRST(2)(src), .Ll_exc_copy) | 398 | LDFIRST(t2, FIRST(2)(src), .Ll_exc_copy) |
379 | EXC( LDFIRST t3, FIRST(3)(src), .Ll_exc_copy) | 399 | LDFIRST(t3, FIRST(3)(src), .Ll_exc_copy) |
380 | EXC( LDREST t2, REST(2)(src), .Ll_exc_copy) | 400 | LDREST(t2, REST(2)(src), .Ll_exc_copy) |
381 | EXC( LDREST t3, REST(3)(src), .Ll_exc_copy) | 401 | LDREST(t3, REST(3)(src), .Ll_exc_copy) |
382 | PREF( 0, 9*32(src) ) # 0 is PREF_LOAD (not streamed) | 402 | PREF( 0, 9*32(src) ) # 0 is PREF_LOAD (not streamed) |
383 | ADD src, src, 4*NBYTES | 403 | ADD src, src, 4*NBYTES |
384 | #ifdef CONFIG_CPU_SB1 | 404 | #ifdef CONFIG_CPU_SB1 |
385 | nop # improves slotting | 405 | nop # improves slotting |
386 | #endif | 406 | #endif |
387 | EXC( STORE t0, UNIT(0)(dst), .Ls_exc_p4u) | 407 | STORE(t0, UNIT(0)(dst), .Ls_exc_p4u) |
388 | EXC( STORE t1, UNIT(1)(dst), .Ls_exc_p3u) | 408 | STORE(t1, UNIT(1)(dst), .Ls_exc_p3u) |
389 | EXC( STORE t2, UNIT(2)(dst), .Ls_exc_p2u) | 409 | STORE(t2, UNIT(2)(dst), .Ls_exc_p2u) |
390 | EXC( STORE t3, UNIT(3)(dst), .Ls_exc_p1u) | 410 | STORE(t3, UNIT(3)(dst), .Ls_exc_p1u) |
391 | PREF( 1, 9*32(dst) ) # 1 is PREF_STORE (not streamed) | 411 | PREF( 1, 9*32(dst) ) # 1 is PREF_STORE (not streamed) |
392 | .set reorder /* DADDI_WAR */ | 412 | .set reorder /* DADDI_WAR */ |
393 | ADD dst, dst, 4*NBYTES | 413 | ADD dst, dst, 4*NBYTES |
@@ -401,11 +421,11 @@ EXC( STORE t3, UNIT(3)(dst), .Ls_exc_p1u) | |||
401 | nop | 421 | nop |
402 | 1: | 422 | 1: |
403 | R10KCBARRIER(0(ra)) | 423 | R10KCBARRIER(0(ra)) |
404 | EXC( LDFIRST t0, FIRST(0)(src), .Ll_exc) | 424 | LDFIRST(t0, FIRST(0)(src), .Ll_exc) |
405 | EXC( LDREST t0, REST(0)(src), .Ll_exc_copy) | 425 | LDREST(t0, REST(0)(src), .Ll_exc_copy) |
406 | ADD src, src, NBYTES | 426 | ADD src, src, NBYTES |
407 | SUB len, len, NBYTES | 427 | SUB len, len, NBYTES |
408 | EXC( STORE t0, 0(dst), .Ls_exc_p1u) | 428 | STORE(t0, 0(dst), .Ls_exc_p1u) |
409 | .set reorder /* DADDI_WAR */ | 429 | .set reorder /* DADDI_WAR */ |
410 | ADD dst, dst, NBYTES | 430 | ADD dst, dst, NBYTES |
411 | bne len, rem, 1b | 431 | bne len, rem, 1b |
@@ -418,10 +438,10 @@ EXC( STORE t0, 0(dst), .Ls_exc_p1u) | |||
418 | /* 0 < len < NBYTES */ | 438 | /* 0 < len < NBYTES */ |
419 | R10KCBARRIER(0(ra)) | 439 | R10KCBARRIER(0(ra)) |
420 | #define COPY_BYTE(N) \ | 440 | #define COPY_BYTE(N) \ |
421 | EXC( lb t0, N(src), .Ll_exc); \ | 441 | LOADB(t0, N(src), .Ll_exc); \ |
422 | SUB len, len, 1; \ | 442 | SUB len, len, 1; \ |
423 | beqz len, .Ldone; \ | 443 | beqz len, .Ldone; \ |
424 | EXC( sb t0, N(dst), .Ls_exc_p1) | 444 | STOREB(t0, N(dst), .Ls_exc_p1) |
425 | 445 | ||
426 | COPY_BYTE(0) | 446 | COPY_BYTE(0) |
427 | COPY_BYTE(1) | 447 | COPY_BYTE(1) |
@@ -431,10 +451,10 @@ EXC( sb t0, N(dst), .Ls_exc_p1) | |||
431 | COPY_BYTE(4) | 451 | COPY_BYTE(4) |
432 | COPY_BYTE(5) | 452 | COPY_BYTE(5) |
433 | #endif | 453 | #endif |
434 | EXC( lb t0, NBYTES-2(src), .Ll_exc) | 454 | LOADB(t0, NBYTES-2(src), .Ll_exc) |
435 | SUB len, len, 1 | 455 | SUB len, len, 1 |
436 | jr ra | 456 | jr ra |
437 | EXC( sb t0, NBYTES-2(dst), .Ls_exc_p1) | 457 | STOREB(t0, NBYTES-2(dst), .Ls_exc_p1) |
438 | .Ldone: | 458 | .Ldone: |
439 | jr ra | 459 | jr ra |
440 | nop | 460 | nop |
@@ -451,11 +471,11 @@ EXC( sb t0, NBYTES-2(dst), .Ls_exc_p1) | |||
451 | * | 471 | * |
452 | * Assumes src < THREAD_BUADDR($28) | 472 | * Assumes src < THREAD_BUADDR($28) |
453 | */ | 473 | */ |
454 | LOAD t0, TI_TASK($28) | 474 | LOADK t0, TI_TASK($28) |
455 | nop | 475 | nop |
456 | LOAD t0, THREAD_BUADDR(t0) | 476 | LOADK t0, THREAD_BUADDR(t0) |
457 | 1: | 477 | 1: |
458 | EXC( lb t1, 0(src), .Ll_exc) | 478 | LOADB(t1, 0(src), .Ll_exc) |
459 | ADD src, src, 1 | 479 | ADD src, src, 1 |
460 | sb t1, 0(dst) # can't fault -- we're copy_from_user | 480 | sb t1, 0(dst) # can't fault -- we're copy_from_user |
461 | .set reorder /* DADDI_WAR */ | 481 | .set reorder /* DADDI_WAR */ |
@@ -463,9 +483,9 @@ EXC( lb t1, 0(src), .Ll_exc) | |||
463 | bne src, t0, 1b | 483 | bne src, t0, 1b |
464 | .set noreorder | 484 | .set noreorder |
465 | .Ll_exc: | 485 | .Ll_exc: |
466 | LOAD t0, TI_TASK($28) | 486 | LOADK t0, TI_TASK($28) |
467 | nop | 487 | nop |
468 | LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address | 488 | LOADK t0, THREAD_BUADDR(t0) # t0 is just past last good address |
469 | nop | 489 | nop |
470 | SUB len, AT, t0 # len number of uncopied bytes | 490 | SUB len, AT, t0 # len number of uncopied bytes |
471 | bnez t6, .Ldone /* Skip the zeroing part if inatomic */ | 491 | bnez t6, .Ldone /* Skip the zeroing part if inatomic */ |