diff options
Diffstat (limited to 'arch/sh/lib/memmove.S')
-rw-r--r-- | arch/sh/lib/memmove.S | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/arch/sh/lib/memmove.S b/arch/sh/lib/memmove.S new file mode 100644 index 00000000000..5a2211f0920 --- /dev/null +++ b/arch/sh/lib/memmove.S @@ -0,0 +1,254 @@ +/* $Id: memmove.S,v 1.2 2001/07/27 11:51:09 gniibe Exp $ + * + * "memmove" implementation of SuperH + * + * Copyright (C) 1999 Niibe Yutaka + * + */ + +/* + * void *memmove(void *dst, const void *src, size_t n); + * The memory areas may overlap. + */ + +#include <linux/linkage.h> +ENTRY(memmove) + ! if dest > src, call memcpy (it copies in decreasing order) + cmp/hi r5,r4 + bf 1f + mov.l 2f,r0 + jmp @r0 + nop + .balign 4 +2: .long memcpy +1: + sub r5,r4 ! From here, r4 has the distance to r0 + tst r6,r6 + bt/s 9f ! if n=0, do nothing + mov r5,r0 + add r6,r5 + mov #12,r1 + cmp/gt r6,r1 + bt/s 8f ! if it's too small, copy a byte at once + add #-1,r4 + add #1,r4 + ! + ! [ ... ] DST [ ... ] SRC + ! [ ... ] [ ... ] + ! : : + ! r0+r4--> [ ... ] r0 --> [ ... ] + ! : : + ! [ ... ] [ ... ] + ! r5 --> + ! + mov r4,r1 + mov #3,r2 + and r2,r1 + shll2 r1 + mov r0,r3 ! Save the value on R0 to R3 + mova jmptable,r0 + add r1,r0 + mov.l @r0,r1 + jmp @r1 + mov r3,r0 ! and back to R0 + .balign 4 +jmptable: + .long case0 + .long case1 + .long case2 + .long case3 + + ! copy a byte at once +8: mov.b @r0+,r1 + cmp/hs r5,r0 + bf/s 8b ! while (r0<r5) + mov.b r1,@(r0,r4) + add #1,r4 +9: + add r4,r0 + rts + sub r6,r0 + +case_none: + bra 8b + add #-1,r4 + +case0: + ! + ! GHIJ KLMN OPQR --> GHIJ KLMN OPQR + ! + ! First, align to long word boundary + mov r0,r3 + and r2,r3 + tst r3,r3 + bt/s 2f + add #-1,r4 + mov #4,r2 + sub r3,r2 +1: dt r2 + mov.b @r0+,r1 + bf/s 1b + mov.b r1,@(r0,r4) + ! +2: ! Second, copy a long word at once + add #-3,r4 + add #-3,r5 +3: mov.l @r0+,r1 + cmp/hs r5,r0 + bf/s 3b + mov.l r1,@(r0,r4) + add #3,r5 + ! + ! Third, copy a byte at once, if necessary + cmp/eq r5,r0 + bt/s 9b + add #4,r4 + bra 8b + add #-1,r4 + +case3: + ! + ! GHIJ KLMN OPQR --> ...G HIJK LMNO PQR. + ! + ! First, align to long word boundary + mov r0,r3 + and r2,r3 + tst r3,r3 + bt/s 2f + add #-1,r4 + mov #4,r2 + sub r3,r2 +1: dt r2 + mov.b @r0+,r1 + bf/s 1b + mov.b r1,@(r0,r4) + ! +2: ! Second, read a long word and write a long word at once + add #-2,r4 + mov.l @(r0,r4),r1 + add #-7,r5 + add #-4,r4 + ! +#ifdef __LITTLE_ENDIAN__ + shll8 r1 +3: mov r1,r3 ! JIHG + shlr8 r3 ! xJIH + mov.l @r0+,r1 ! NMLK + mov r1,r2 + shll16 r2 + shll8 r2 ! Kxxx + or r2,r3 ! KJIH + cmp/hs r5,r0 + bf/s 3b + mov.l r3,@(r0,r4) +#else + shlr8 r1 +3: mov r1,r3 ! GHIJ + shll8 r3 ! HIJx + mov.l @r0+,r1 ! KLMN + mov r1,r2 + shlr16 r2 + shlr8 r2 ! xxxK + or r2,r3 ! HIJK + cmp/hs r5,r0 + bf/s 3b + mov.l r3,@(r0,r4) +#endif + add #7,r5 + ! + ! Third, copy a byte at once, if necessary + cmp/eq r5,r0 + bt/s 9b + add #7,r4 + add #-3,r0 + bra 8b + add #-1,r4 + +case2: + ! + ! GHIJ KLMN OPQR --> ..GH IJKL MNOP QR.. + ! + ! First, align to word boundary + tst #1,r0 + bt/s 2f + add #-1,r4 + mov.b @r0+,r1 + mov.b r1,@(r0,r4) + ! +2: ! Second, read a word and write a word at once + add #-1,r4 + add #-1,r5 + ! +3: mov.w @r0+,r1 + cmp/hs r5,r0 + bf/s 3b + mov.w r1,@(r0,r4) + add #1,r5 + ! + ! Third, copy a byte at once, if necessary + cmp/eq r5,r0 + bt/s 9b + add #2,r4 + mov.b @r0,r1 + mov.b r1,@(r0,r4) + bra 9b + add #1,r0 + +case1: + ! + ! GHIJ KLMN OPQR --> .GHI JKLM NOPQ R... + ! + ! First, align to long word boundary + mov r0,r3 + and r2,r3 + tst r3,r3 + bt/s 2f + add #-1,r4 + mov #4,r2 + sub r3,r2 +1: dt r2 + mov.b @r0+,r1 + bf/s 1b + mov.b r1,@(r0,r4) + ! +2: ! Second, read a long word and write a long word at once + mov.l @(r0,r4),r1 + add #-7,r5 + add #-4,r4 + ! +#ifdef __LITTLE_ENDIAN__ + shll16 r1 + shll8 r1 +3: mov r1,r3 ! JIHG + shlr16 r3 + shlr8 r3 ! xxxJ + mov.l @r0+,r1 ! NMLK + mov r1,r2 + shll8 r2 ! MLKx + or r2,r3 ! MLKJ + cmp/hs r5,r0 + bf/s 3b + mov.l r3,@(r0,r4) +#else + shlr16 r1 + shlr8 r1 +3: mov r1,r3 ! GHIJ + shll16 r3 + shll8 r3 ! Jxxx + mov.l @r0+,r1 ! KLMN + mov r1,r2 + shlr8 r2 ! xKLM + or r2,r3 ! JKLM + cmp/hs r5,r0 + bf/s 3b ! while(r0<r5) + mov.l r3,@(r0,r4) +#endif + add #7,r5 + ! + ! Third, copy a byte at once, if necessary + cmp/eq r5,r0 + bt/s 9b + add #5,r4 + add #-3,r0 + bra 8b + add #-1,r4 |