mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
255 lines
4.0 KiB
255 lines
4.0 KiB
/* 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
|
|
|