/* SPDX-License-Identifier: GPL-2.0 */ /* $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