#include <machine/asm.h>
#if defined(LIBC_SCCS) && !defined(lint)
RCSID("$NetBSD: memcpy.S,v 1.3 2024/02/07 04:20:25 msaitoh Exp $")
#endif
#if !defined(MEMCOPY) && !defined(MEMMOVE) && !defined(BCOPY)
#define MEMCOPY
#endif
#if defined(MEMCOPY) || defined(MEMMOVE)
#define REG_DST0 r3
#define REG_SRC r5
#define REG_DST r4
#else
#define REG_SRC r4
#define REG_DST r5
#endif
#define REG_LEN r6
#if defined(MEMCOPY)
ENTRY(memcpy)
#elif defined(MEMMOVE)
ENTRY(memmove)
#elif defined(BCOPY)
ENTRY(bcopy)
#endif
#ifdef REG_DST0
mov REG_DST,REG_DST0
#endif
cmp/eq REG_DST,REG_SRC
bt/s bcopy_return
cmp/hi REG_DST,REG_SRC
bf/s bcopy_overlap
mov REG_SRC,r0
xor REG_DST,r0
and #3,r0
mov r0,r1
tst r0,r0
bf/s word_align
longword_align:
tst REG_LEN,REG_LEN
bt/s bcopy_return
mov REG_SRC,r0
tst #1,r0
bt 1f
mov.b @REG_SRC+,r0
add #-1,REG_LEN
mov.b r0,@REG_DST
add #1,REG_DST
1:
mov #1,r0
cmp/hi r0,REG_LEN
bf/s 1f
mov REG_SRC,r0
tst #2,r0
bt 1f
mov.w @REG_SRC+,r0
add #-2,REG_LEN
mov.w r0,@REG_DST
add #2,REG_DST
1:
mov #3,r1
cmp/hi r1,REG_LEN
bf/s no_align_delay
tst REG_LEN,REG_LEN
2:
mov.l @REG_SRC+,r0
add #-4,REG_LEN
mov.l r0,@REG_DST
cmp/hi r1,REG_LEN
bt/s 2b
add #4,REG_DST
bra no_align_delay
tst REG_LEN,REG_LEN
word_align:
mov r1,r0
tst #1,r0
bf/s no_align_delay
tst REG_LEN,REG_LEN
bt bcopy_return
mov REG_SRC,r0
tst #1,r0
bt 1f
mov.b @REG_SRC+,r0
add #-1,REG_LEN
mov.b r0,@REG_DST
add #1,REG_DST
1:
mov #1,r1
cmp/hi r1,REG_LEN
bf/s no_align_delay
tst REG_LEN,REG_LEN
2:
mov.w @REG_SRC+,r0
add #-2,REG_LEN
mov.w r0,@REG_DST
cmp/hi r1,REG_LEN
bt/s 2b
add #2,REG_DST
no_align:
tst REG_LEN,REG_LEN
no_align_delay:
bt bcopy_return
1:
mov.b @REG_SRC+,r0
add #-1,REG_LEN
mov.b r0,@REG_DST
tst REG_LEN,REG_LEN
bf/s 1b
add #1,REG_DST
bcopy_return:
rts
#ifdef REG_DST0
mov REG_DST0,r0
#else
nop
#endif
bcopy_overlap:
add REG_LEN,REG_SRC
add REG_LEN,REG_DST
mov REG_SRC,r0
xor REG_DST,r0
and #3,r0
mov r0,r1
tst r0,r0
bf/s ov_word_align
ov_longword_align:
tst REG_LEN,REG_LEN
bt/s bcopy_return
mov REG_SRC,r0
tst #1,r0
bt 1f
add #-1,REG_SRC
mov.b @REG_SRC,r0
mov.b r0,@-REG_DST
add #-1,REG_LEN
1:
mov #1,r0
cmp/hi r0,REG_LEN
bf/s 1f
mov REG_SRC,r0
tst #2,r0
bt 1f
add #-2,REG_SRC
mov.w @REG_SRC,r0
add #-2,REG_LEN
mov.w r0,@-REG_DST
1:
mov #3,r1
cmp/hi r1,REG_LEN
bf/s ov_no_align_delay
tst REG_LEN,REG_LEN
2:
add #-4,REG_SRC
mov.l @REG_SRC,r0
add #-4,REG_LEN
cmp/hi r1,REG_LEN
bt/s 2b
mov.l r0,@-REG_DST
bra ov_no_align_delay
tst REG_LEN,REG_LEN
ov_word_align:
mov r1,r0
tst #1,r0
bf/s ov_no_align_delay
tst REG_LEN,REG_LEN
bt bcopy_return
mov REG_SRC,r0
tst #1,r0
bt 1f
add #-1,REG_SRC
mov.b @REG_SRC,r0
add #-1,REG_LEN
mov.b r0,@-REG_DST
1:
mov #1,r1
cmp/hi r1,REG_LEN
bf/s ov_no_align_delay
tst REG_LEN,REG_LEN
2:
add #-2,REG_SRC
mov.w @REG_SRC,r0
add #-2,REG_LEN
cmp/hi r1,REG_LEN
bt/s 2b
mov.w r0,@-REG_DST
ov_no_align:
tst REG_LEN,REG_LEN
ov_no_align_delay:
bt 9f
1:
add #-1,REG_SRC
mov.b @REG_SRC,r0
add #-1,REG_LEN
tst REG_LEN,REG_LEN
bf/s 1b
mov.b r0,@-REG_DST
9:
rts
#ifdef REG_DST0
mov REG_DST0,r0
#else
nop
#endif