123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- /* $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
|