diff options
| -rw-r--r-- | arch/sparc/lib/memmove.S | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/arch/sparc/lib/memmove.S b/arch/sparc/lib/memmove.S index b7f6334e159f..857ad4f8905f 100644 --- a/arch/sparc/lib/memmove.S +++ b/arch/sparc/lib/memmove.S | |||
| @@ -8,9 +8,11 @@ | |||
| 8 | 8 | ||
| 9 | .text | 9 | .text |
| 10 | ENTRY(memmove) /* o0=dst o1=src o2=len */ | 10 | ENTRY(memmove) /* o0=dst o1=src o2=len */ |
| 11 | mov %o0, %g1 | 11 | brz,pn %o2, 99f |
| 12 | mov %o0, %g1 | ||
| 13 | |||
| 12 | cmp %o0, %o1 | 14 | cmp %o0, %o1 |
| 13 | bleu,pt %xcc, memcpy | 15 | bleu,pt %xcc, 2f |
| 14 | add %o1, %o2, %g7 | 16 | add %o1, %o2, %g7 |
| 15 | cmp %g7, %o0 | 17 | cmp %g7, %o0 |
| 16 | bleu,pt %xcc, memcpy | 18 | bleu,pt %xcc, memcpy |
| @@ -24,7 +26,34 @@ ENTRY(memmove) /* o0=dst o1=src o2=len */ | |||
| 24 | stb %g7, [%o0] | 26 | stb %g7, [%o0] |
| 25 | bne,pt %icc, 1b | 27 | bne,pt %icc, 1b |
| 26 | sub %o0, 1, %o0 | 28 | sub %o0, 1, %o0 |
| 27 | 29 | 99: | |
| 28 | retl | 30 | retl |
| 29 | mov %g1, %o0 | 31 | mov %g1, %o0 |
| 32 | |||
| 33 | /* We can't just call memcpy for these memmove cases. On some | ||
| 34 | * chips the memcpy uses cache initializing stores and when dst | ||
| 35 | * and src are close enough, those can clobber the source data | ||
| 36 | * before we've loaded it in. | ||
| 37 | */ | ||
| 38 | 2: or %o0, %o1, %g7 | ||
| 39 | or %o2, %g7, %g7 | ||
| 40 | andcc %g7, 0x7, %g0 | ||
| 41 | bne,pn %xcc, 4f | ||
| 42 | nop | ||
| 43 | |||
| 44 | 3: ldx [%o1], %g7 | ||
| 45 | add %o1, 8, %o1 | ||
| 46 | subcc %o2, 8, %o2 | ||
| 47 | add %o0, 8, %o0 | ||
| 48 | bne,pt %icc, 3b | ||
| 49 | stx %g7, [%o0 - 0x8] | ||
| 50 | ba,a,pt %xcc, 99b | ||
| 51 | |||
| 52 | 4: ldub [%o1], %g7 | ||
| 53 | add %o1, 1, %o1 | ||
| 54 | subcc %o2, 1, %o2 | ||
| 55 | add %o0, 1, %o0 | ||
| 56 | bne,pt %icc, 4b | ||
| 57 | stb %g7, [%o0 - 0x1] | ||
| 58 | ba,a,pt %xcc, 99b | ||
| 30 | ENDPROC(memmove) | 59 | ENDPROC(memmove) |
