mirror of
https://github.com/torvalds/linux.git
synced 2024-12-16 08:02:17 +00:00
228 lines
3.6 KiB
ArmAsm
228 lines
3.6 KiB
ArmAsm
|
/* $Id: memcpy.S,v 1.3 2001/07/27 11:50:52 gniibe Exp $
|
||
|
*
|
||
|
* "memcpy" implementation of SuperH
|
||
|
*
|
||
|
* Copyright (C) 1999 Niibe Yutaka
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* void *memcpy(void *dst, const void *src, size_t n);
|
||
|
* No overlap between the memory of DST and of SRC are assumed.
|
||
|
*/
|
||
|
|
||
|
#include <linux/linkage.h>
|
||
|
ENTRY(memcpy)
|
||
|
tst r6,r6
|
||
|
bt/s 9f ! if n=0, do nothing
|
||
|
mov r4,r0
|
||
|
sub r4,r5 ! From here, r5 has the distance to r0
|
||
|
add r6,r0 ! From here, r0 points the end of copying point
|
||
|
mov #12,r1
|
||
|
cmp/gt r6,r1
|
||
|
bt/s 7f ! if it's too small, copy a byte at once
|
||
|
add #-1,r5
|
||
|
add #1,r5
|
||
|
! From here, r6 is free
|
||
|
!
|
||
|
! r4 --> [ ... ] DST [ ... ] SRC
|
||
|
! [ ... ] [ ... ]
|
||
|
! : :
|
||
|
! r0 --> [ ... ] r0+r5 --> [ ... ]
|
||
|
!
|
||
|
!
|
||
|
mov r5,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
|
||
|
7: mov r4,r2
|
||
|
add #1,r2
|
||
|
8:
|
||
|
cmp/hi r2,r0
|
||
|
mov.b @(r0,r5),r1
|
||
|
bt/s 8b ! while (r0>r2)
|
||
|
mov.b r1,@-r0
|
||
|
9:
|
||
|
rts
|
||
|
nop
|
||
|
|
||
|
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 #-4,r5
|
||
|
add #3,r5
|
||
|
1: dt r3
|
||
|
mov.b @(r0,r5),r1
|
||
|
bf/s 1b
|
||
|
mov.b r1,@-r0
|
||
|
!
|
||
|
add #-3,r5
|
||
|
2: ! Second, copy a long word at once
|
||
|
mov r4,r2
|
||
|
add #7,r2
|
||
|
3: mov.l @(r0,r5),r1
|
||
|
cmp/hi r2,r0
|
||
|
bt/s 3b
|
||
|
mov.l r1,@-r0
|
||
|
!
|
||
|
! Third, copy a byte at once, if necessary
|
||
|
cmp/eq r4,r0
|
||
|
bt/s 9b
|
||
|
add #3,r5
|
||
|
bra 8b
|
||
|
add #-6,r2
|
||
|
|
||
|
case1:
|
||
|
!
|
||
|
! 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,r5
|
||
|
1: dt r3
|
||
|
mov.b @(r0,r5),r1
|
||
|
bf/s 1b
|
||
|
mov.b r1,@-r0
|
||
|
!
|
||
|
2: ! Second, read a long word and write a long word at once
|
||
|
mov.l @(r0,r5),r1
|
||
|
add #-4,r5
|
||
|
mov r4,r2
|
||
|
add #7,r2
|
||
|
!
|
||
|
#ifdef __LITTLE_ENDIAN__
|
||
|
3: mov r1,r3 ! RQPO
|
||
|
shll16 r3
|
||
|
shll8 r3 ! Oxxx
|
||
|
mov.l @(r0,r5),r1 ! NMLK
|
||
|
mov r1,r6
|
||
|
shlr8 r6 ! xNML
|
||
|
or r6,r3 ! ONML
|
||
|
cmp/hi r2,r0
|
||
|
bt/s 3b
|
||
|
mov.l r3,@-r0
|
||
|
#else
|
||
|
3: mov r1,r3 ! OPQR
|
||
|
shlr16 r3
|
||
|
shlr8 r3 ! xxxO
|
||
|
mov.l @(r0,r5),r1 ! KLMN
|
||
|
mov r1,r6
|
||
|
shll8 r6 ! LMNx
|
||
|
or r6,r3 ! LMNO
|
||
|
cmp/hi r2,r0
|
||
|
bt/s 3b
|
||
|
mov.l r3,@-r0
|
||
|
#endif
|
||
|
!
|
||
|
! Third, copy a byte at once, if necessary
|
||
|
cmp/eq r4,r0
|
||
|
bt/s 9b
|
||
|
add #4,r5
|
||
|
bra 8b
|
||
|
add #-6,r2
|
||
|
|
||
|
case2:
|
||
|
!
|
||
|
! GHIJ KLMN OPQR --> ..GH IJKL MNOP QR..
|
||
|
!
|
||
|
! First, align to word boundary
|
||
|
tst #1,r0
|
||
|
bt/s 2f
|
||
|
add #-1,r5
|
||
|
mov.b @(r0,r5),r1
|
||
|
mov.b r1,@-r0
|
||
|
!
|
||
|
2: ! Second, read a word and write a word at once
|
||
|
add #-1,r5
|
||
|
mov r4,r2
|
||
|
add #3,r2
|
||
|
!
|
||
|
3: mov.w @(r0,r5),r1
|
||
|
cmp/hi r2,r0
|
||
|
bt/s 3b
|
||
|
mov.w r1,@-r0
|
||
|
!
|
||
|
! Third, copy a byte at once, if necessary
|
||
|
cmp/eq r4,r0
|
||
|
bt/s 9b
|
||
|
add #1,r5
|
||
|
mov.b @(r0,r5),r1
|
||
|
rts
|
||
|
mov.b r1,@-r0
|
||
|
|
||
|
case3:
|
||
|
!
|
||
|
! 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,r5
|
||
|
1: dt r3
|
||
|
mov.b @(r0,r5),r1
|
||
|
bf/s 1b
|
||
|
mov.b r1,@-r0
|
||
|
!
|
||
|
2: ! Second, read a long word and write a long word at once
|
||
|
add #-2,r5
|
||
|
mov.l @(r0,r5),r1
|
||
|
add #-4,r5
|
||
|
mov r4,r2
|
||
|
add #7,r2
|
||
|
!
|
||
|
#ifdef __LITTLE_ENDIAN__
|
||
|
3: mov r1,r3 ! RQPO
|
||
|
shll8 r3 ! QPOx
|
||
|
mov.l @(r0,r5),r1 ! NMLK
|
||
|
mov r1,r6
|
||
|
shlr16 r6
|
||
|
shlr8 r6 ! xxxN
|
||
|
or r6,r3 ! QPON
|
||
|
cmp/hi r2,r0
|
||
|
bt/s 3b
|
||
|
mov.l r3,@-r0
|
||
|
#else
|
||
|
3: mov r1,r3 ! OPQR
|
||
|
shlr8 r3 ! xOPQ
|
||
|
mov.l @(r0,r5),r1 ! KLMN
|
||
|
mov r1,r6
|
||
|
shll16 r6
|
||
|
shll8 r6 ! Nxxx
|
||
|
or r6,r3 ! NOPQ
|
||
|
cmp/hi r2,r0
|
||
|
bt/s 3b
|
||
|
mov.l r3,@-r0
|
||
|
#endif
|
||
|
!
|
||
|
! Third, copy a byte at once, if necessary
|
||
|
cmp/eq r4,r0
|
||
|
bt/s 9b
|
||
|
add #6,r5
|
||
|
bra 8b
|
||
|
add #-6,r2
|