#include <machine/asm.h>
#if defined(LIBC_SCCS)
RCSID("$NetBSD: bcopy.S,v 1.4 2024/02/07 04:20:25 msaitoh Exp $")
#endif
#if defined(MEMCOPY)
#define FUNCTION memcpy
#define NO_OVERLAP
#define SRC0 x1
#define DST0 x0
#define LEN x2
#elif defined(MEMMOVE)
#define FUNCTION memmove
#undef NO_OVERLAP
#define SRC0 x1
#define DST0 x0
#define LEN x2
#else
#define FUNCTION bcopy
#define NO_OVERLAP
#define SRC0 x0
#define DST0 x1
#define LEN x2
#endif
#define TMP_X x3
#define TMP_Xw w3
#define TMP_D x4
#define TMP_S x5
#define DST x6
#define SRC x7
#define DATA0 x8
#define DATA0w w8
#define DATA1 x9
#define DATA1w w9
#define DATA2 x10
#define SRC_ALIGNBIT x11
#define DST_ALIGNBIT x12
#define SRC_DST_ALIGNBIT x13
#define DST_SRC_ALIGNBIT x14
#define STP_ALIGN 16
#define SMALLSIZE 32
.text
.align 5
#ifndef NO_OVERLAP
#ifndef STRICT_ALIGNMENT
backward_ignore_align:
prfm PLDL1KEEP, [SRC0]
add SRC0, SRC0, LEN
add DST, DST0, LEN
cmp LEN, #SMALLSIZE
bcs copy_backward
copy_backward_small:
cmp LEN, #8
bcs 9f
tbz LEN, #2, 1f
ldr TMP_Xw, [SRC0, #-4]!
str TMP_Xw, [DST, #-4]!
1:
tbz LEN, #1, 1f
ldrh TMP_Xw, [SRC0, #-2]!
strh TMP_Xw, [DST, #-2]!
1:
tbz LEN, #0, 1f
ldrb TMP_Xw, [SRC0, #-1]!
strb TMP_Xw, [DST, #-1]!
1:
ret
9:
cmp LEN, #16
bcs 9f
ldr TMP_X, [SRC0, #-8]!
str TMP_X, [DST, #-8]!
tbz LEN, #2, 1f
ldr TMP_Xw, [SRC0, #-4]!
str TMP_Xw, [DST, #-4]!
1:
tbz LEN, #1, 1f
ldrh TMP_Xw, [SRC0, #-2]!
strh TMP_Xw, [DST, #-2]!
1:
tbz LEN, #0, 1f
ldrb TMP_Xw, [SRC0, #-1]!
strb TMP_Xw, [DST, #-1]!
1:
ret
9:
ldp DATA0, DATA1, [SRC0, #-16]!
stp DATA0, DATA1, [DST, #-16]!
tbz LEN, #3, 1f
ldr TMP_X, [SRC0, #-8]!
str TMP_X, [DST, #-8]!
1:
tbz LEN, #2, 1f
ldr TMP_Xw, [SRC0, #-4]!
str TMP_Xw, [DST, #-4]!
1:
tbz LEN, #1, 1f
ldrh TMP_Xw, [SRC0, #-2]!
strh TMP_Xw, [DST, #-2]!
1:
tbz LEN, #0, 1f
ldrb TMP_Xw, [SRC0, #-1]!
strb TMP_Xw, [DST, #-1]!
1:
ret
#endif
.align 4
copy_backward:
#ifndef STRICT_ALIGNMENT
cmp LEN, #512
bcc 9f
#endif
tbz DST, #0, 1f
ldrb TMP_Xw, [SRC0, #-1]!
strb TMP_Xw, [DST, #-1]!
sub LEN, LEN, #1
1:
tbz DST, #1, 1f
ldrh TMP_Xw, [SRC0, #-2]!
strh TMP_Xw, [DST, #-2]!
sub LEN, LEN, #2
1:
tbz DST, #2, 1f
ldr TMP_Xw, [SRC0, #-4]!
str TMP_Xw, [DST, #-4]!
sub LEN, LEN, #4
1:
#if (STP_ALIGN > 8)
tbz DST, #3, 1f
ldr TMP_X, [SRC0, #-8]!
str TMP_X, [DST, #-8]!
sub LEN, LEN, #8
1:
#endif
9:
backward_copy1k:
cmp LEN, #1024
blo 9f
1:
sub LEN, LEN, #1024
.rept (1024 / 16)
ldp DATA0, DATA1, [SRC0, #-16]!
stp DATA0, DATA1, [DST, #-16]!
.endr
cmp LEN, #1024
bhs 1b
9:
tbz LEN, #9, 1f
.rept (512 / 16)
ldp DATA0, DATA1, [SRC0, #-16]!
stp DATA0, DATA1, [DST, #-16]!
.endr
1:
tbz LEN, #8, 1f
.rept (256 / 16)
ldp DATA0, DATA1, [SRC0, #-16]!
stp DATA0, DATA1, [DST, #-16]!
.endr
1:
tbz LEN, #7, 1f
.rept (128 / 16)
ldp DATA0, DATA1, [SRC0, #-16]!
stp DATA0, DATA1, [DST, #-16]!
.endr
1:
tbz LEN, #6, 1f
.rept (64 / 16)
ldp DATA0, DATA1, [SRC0, #-16]!
stp DATA0, DATA1, [DST, #-16]!
.endr
1:
tbz LEN, #5, 1f
.rept (32 / 16)
ldp DATA0, DATA1, [SRC0, #-16]!
stp DATA0, DATA1, [DST, #-16]!
.endr
1:
tbz LEN, #4, 1f
ldp DATA0, DATA1, [SRC0, #-16]!
stp DATA0, DATA1, [DST, #-16]!
1:
tbz LEN, #3, 1f
ldr TMP_X, [SRC0, #-8]!
str TMP_X, [DST, #-8]!
1:
tbz LEN, #2, 1f
ldr TMP_Xw, [SRC0, #-4]!
str TMP_Xw, [DST, #-4]!
1:
tbz LEN, #1, 1f
ldrh TMP_Xw, [SRC0, #-2]!
strh TMP_Xw, [DST, #-2]!
1:
tbz LEN, #0, 1f
ldrb TMP_Xw, [SRC0, #-1]!
strb TMP_Xw, [DST, #-1]!
1:
ret
#endif
#if defined(STRICT_ALIGNMENT) && !defined(NO_OVERLAP)
.align 5
backward_copy:
prfm PLDL1KEEP, [SRC0]
add DST, DST0, LEN
add SRC0, SRC0, LEN
cmp LEN, #SMALLSIZE
bcs strict_backward
cmp LEN, #10
bcs 9f
backward_tiny:
1: sub LEN, LEN, #1
ldrb TMP_Xw, [SRC0, #-1]!
strb TMP_Xw, [DST, #-1]!
cbz LEN, 1b
ret
9:
eor TMP_X, SRC0, DST
ands TMP_X, TMP_X, #7
bne notaligned_backward_small
samealign_backward_small:
tbz DST, #0, 1f
ldrb TMP_Xw, [SRC0, #-1]!
strb TMP_Xw, [DST, #-1]!
sub LEN, LEN, #1
1:
tbz DST, #1, 1f
ldrh TMP_Xw, [SRC0, #-2]!
strh TMP_Xw, [DST, #-2]!
sub LEN, LEN, #2
1:
tbz DST, #2, 1f
ldr TMP_Xw, [SRC0, #-4]!
str TMP_Xw, [DST, #-4]!
sub LEN, LEN, #4
1:
tbz LEN, #4, 1f
ldp DATA0, DATA1, [SRC0, #-16]!
stp DATA0, DATA1, [DST, #-16]!
1:
tbz LEN, #3, 1f
ldr TMP_X, [SRC0, #-8]!
str TMP_X, [DST, #-8]!
1:
tbz LEN, #2, 1f
ldr TMP_Xw, [SRC0, #-4]!
str TMP_Xw, [DST, #-4]!
1:
tbz LEN, #1, 1f
ldrh TMP_Xw, [SRC0, #-2]!
strh TMP_Xw, [DST, #-2]!
1:
tbz LEN, #0, 1f
ldrb TMP_Xw, [SRC0, #-1]!
strb TMP_Xw, [DST, #-1]!
1:
ret
notaligned_backward_small:
sub TMP_S, SRC0, LEN
1:
ldrb TMP_Xw, [SRC0, #-1]!
strb TMP_Xw, [DST, #-1]!
cmp TMP_S, SRC0
blo 1b
ret
strict_backward:
and SRC_ALIGNBIT, SRC0, #7
and DST_ALIGNBIT, DST, #7
lsl SRC_ALIGNBIT, SRC_ALIGNBIT, #3
lsl DST_ALIGNBIT, DST_ALIGNBIT, #3
sub SRC_DST_ALIGNBIT, SRC_ALIGNBIT, DST_ALIGNBIT
cbz SRC_DST_ALIGNBIT, copy_backward
and SRC, SRC0, #~7
and DST, DST, #~7
neg DST_SRC_ALIGNBIT, SRC_DST_ALIGNBIT
#if BYTE_ORDER == LITTLE_ENDIAN
tbz SRC_DST_ALIGNBIT, #63, 5f
cmp SRC, SRC0
beq 1f
ldr DATA1, [SRC]
1:
ldr DATA0, [SRC, #-8]!
lsl DATA1, DATA1, DST_SRC_ALIGNBIT
lsr TMP_X, DATA0, SRC_DST_ALIGNBIT
orr DATA1, DATA1, TMP_X
b 9f
5:
ldr DATA0, [SRC]
lsr DATA1, DATA0, SRC_DST_ALIGNBIT
9:
cbz DST_ALIGNBIT, 9f
mov TMP_D, DST
tbz DST_ALIGNBIT, #(2+3), 1f
str DATA1w, [TMP_D], #4
lsr DATA1, DATA1, #32
1:
tbz DST_ALIGNBIT, #(1+3), 1f
strh DATA1w, [TMP_D], #2
lsr DATA1, DATA1, #16
1:
tbz DST_ALIGNBIT, #(0+3), 1f
strb DATA1w, [TMP_D]
1:
sub LEN, LEN, DST_ALIGNBIT, lsr #3
9:
#else
tbz SRC_DST_ALIGNBIT, #63, 5f
cmp SRC, SRC0
beq 1f
ldr DATA1, [SRC]
1:
ldr DATA0, [SRC, #-8]!
lsr DATA1, DATA1, DST_SRC_ALIGNBIT
lsl TMP_X, DATA0, SRC_DST_ALIGNBIT
orr DATA1, DATA1, TMP_X
b 9f
5:
ldr DATA0, [SRC]
lsr DATA1, DATA0, DST_SRC_ALIGNBIT
9:
cbz DST_ALIGNBIT, 9f
mov TMP_D, DST
tbz DST_ALIGNBIT, #(2+3), 1f
lsr TMP_X, DATA1, #32
str TMP_Xw, [TMP_D], #4
1:
tbz DST_ALIGNBIT, #(1+3), 1f
lsr TMP_X, DATA1, #16
strh TMP_Xw, [TMP_D], #2
1:
tbz DST_ALIGNBIT, #(0+3), 1f
lsr TMP_X, DATA1, #8
strb TMP_Xw, [TMP_D], #1
1:
sub LEN, LEN, DST_ALIGNBIT, lsr #3
9:
#endif
backward_shifting_copy_loop:
ldp DATA2, DATA1, [SRC, #-16]!
#if BYTE_ORDER == LITTLE_ENDIAN
lsl DATA0, DATA0, DST_SRC_ALIGNBIT
lsr TMP_X, DATA1, SRC_DST_ALIGNBIT
orr DATA0, DATA0, TMP_X
lsl DATA1, DATA1, DST_SRC_ALIGNBIT
lsr TMP_X, DATA2, SRC_DST_ALIGNBIT
orr DATA1, DATA1, TMP_X
#else
lsr DATA0, DATA0, DST_SRC_ALIGNBIT
lsl TMP_X, DATA1, SRC_DST_ALIGNBIT
orr DATA0, DATA0, TMP_X
lsr DATA1, DATA1, DST_SRC_ALIGNBIT
lsl TMP_X, DATA2, SRC_DST_ALIGNBIT
orr DATA1, DATA1, TMP_X
#endif
stp DATA1, DATA0, [DST, #-16]!
mov DATA0, DATA2
sub LEN, LEN, #16
cmp LEN, #16
bhs backward_shifting_copy_loop
tbz LEN, #3, 9f
ldr DATA1, [SRC, #-8]!
#if BYTE_ORDER == LITTLE_ENDIAN
lsl DATA0, DATA0, DST_SRC_ALIGNBIT
lsr TMP_X, DATA1, SRC_DST_ALIGNBIT
orr DATA0, DATA0, TMP_X
#else
lsr DATA0, DATA0, DST_SRC_ALIGNBIT
lsl TMP_X, DATA1, SRC_DST_ALIGNBIT
orr DATA0, DATA0, TMP_X
#endif
str DATA0, [DST, #-8]!
mov DATA0, DATA1
sub LEN, LEN, #8
9:
cbz LEN, backward_shifting_copy_done
and TMP_X, SRC_DST_ALIGNBIT, #63
cmp LEN, TMP_X, lsr #3
bls 1f
ldr DATA1, [SRC, #-8]!
1:
#if BYTE_ORDER == LITTLE_ENDIAN
lsl DATA0, DATA0, DST_SRC_ALIGNBIT
lsr TMP_X, DATA1, SRC_DST_ALIGNBIT
orr DATA0, DATA0, TMP_X
#else
lsr DATA0, DATA0, DST_SRC_ALIGNBIT
lsl TMP_X, DATA1, SRC_DST_ALIGNBIT
orr DATA0, DATA0, TMP_X
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
tbz LEN, #2, 1f
ror DATA0, DATA0, #32
str DATA0w, [DST, #-4]!
1:
tbz LEN, #1, 1f
ror DATA0, DATA0, #48
strh DATA0w, [DST, #-2]!
1:
tbz LEN, #0, 1f
ror DATA0, DATA0, #56
strb DATA0w, [DST, #-1]!
1:
#else
tbz LEN, #2, 1f
str DATA0w, [DST, #-4]!
lsr DATA0, DATA0, #32
1:
tbz LEN, #1, 1f
strh DATA0w, [DST, #-2]!
lsr DATA0, DATA0, #16
1:
tbz LEN, #0, 1f
strb DATA0w, [DST, #-1]!
1:
#endif
backward_shifting_copy_done:
ret
#endif
.align 5
ENTRY(FUNCTION)
#ifdef STRICT_ALIGNMENT
cbz LEN, done
#ifndef NO_OVERLAP
cmp SRC0, DST0
beq done
bcc backward_copy
#endif
mov DST, DST0
cmp LEN, #SMALLSIZE
bcs strict_forward
cmp LEN, #10
bcs 9f
forward_tiny:
1: sub LEN, LEN, #1
ldrb TMP_Xw, [SRC0], #1
strb TMP_Xw, [DST], #1
cbz LEN, 1b
ret
9:
eor TMP_X, SRC0, DST0
ands TMP_X, TMP_X, #7
bne notaligned_forward_small
samealign_forward_small:
tbz DST, #0, 1f
ldrb TMP_Xw, [SRC0], #1
strb TMP_Xw, [DST], #1
sub LEN, LEN, #1
1:
tbz DST, #1, 1f
ldrh TMP_Xw, [SRC0], #2
strh TMP_Xw, [DST], #2
sub LEN, LEN, #2
1:
tbz DST, #2, 1f
ldr TMP_Xw, [SRC0], #4
str TMP_Xw, [DST], #4
sub LEN, LEN, #4
1:
tbz LEN, #4, 1f
ldp DATA0, DATA1, [SRC0], #16
stp DATA0, DATA1, [DST], #16
1:
tbz LEN, #3, 1f
ldr TMP_X, [SRC0], #8
str TMP_X, [DST], #8
1:
tbz LEN, #2, 1f
ldr TMP_Xw, [SRC0], #4
str TMP_Xw, [DST], #4
1:
tbz LEN, #1, 1f
ldrh TMP_Xw, [SRC0], #2
strh TMP_Xw, [DST], #2
1:
tbz LEN, #0, 1f
ldrb TMP_Xw, [SRC0], #1
strb TMP_Xw, [DST], #1
1:
ret
notaligned_forward_small:
prfm PLDL1KEEP, [SRC0]
prfm PLDL1KEEP, [SRC0, #8]
prfm PLDL1KEEP, [SRC0, #16]
add TMP_S, SRC0, LEN
1:
ldrb TMP_Xw, [SRC0], #1
strb TMP_Xw, [DST], #1
cmp SRC0, TMP_S
blo 1b
ret
strict_forward:
and SRC_ALIGNBIT, SRC0, #7
and DST_ALIGNBIT, DST0, #7
lsl SRC_ALIGNBIT, SRC_ALIGNBIT, #3
lsl DST_ALIGNBIT, DST_ALIGNBIT, #3
sub SRC_DST_ALIGNBIT, SRC_ALIGNBIT, DST_ALIGNBIT
cbz SRC_DST_ALIGNBIT, copy_forward
and SRC, SRC0, #~7
and DST, DST0, #~7
neg DST_SRC_ALIGNBIT, SRC_DST_ALIGNBIT
#if BYTE_ORDER == LITTLE_ENDIAN
tbz DST_SRC_ALIGNBIT, #63, 5f
ldp DATA1, DATA0, [SRC], #16
neg TMP_X, SRC_ALIGNBIT
lsr DATA1, DATA1, SRC_ALIGNBIT
lsl TMP_X, DATA0, TMP_X
orr DATA1, DATA1, TMP_X
b 9f
5:
ldr DATA0, [SRC], #8
lsr DATA1, DATA0, SRC_ALIGNBIT
9:
cbz DST_ALIGNBIT, 5f
mov TMP_D, DST0
tbz TMP_D, #0, 1f
strb DATA1w, [TMP_D], #1
lsr DATA1, DATA1, #8
1:
tbz TMP_D, #1, 1f
strh DATA1w, [TMP_D], #2
lsr DATA1, DATA1, #16
1:
tbz TMP_D, #2, 1f
str DATA1w, [TMP_D], #4
1:
add DST, DST, #8
b 9f
5:
str DATA1, [DST], #8
9:
sub LEN, LEN, #8
add LEN, LEN, DST_ALIGNBIT, lsr #3
#else
tbz DST_SRC_ALIGNBIT, #63, 5f
ldp DATA1, DATA0, [SRC], #16
neg TMP_X, SRC_ALIGNBIT
lsl DATA1, DATA1, SRC_ALIGNBIT
lsr TMP_X, DATA0, TMP_X
orr DATA1, DATA1, TMP_X
b 9f
5:
ldr DATA0, [SRC], #8
lsl DATA1, DATA0, SRC_ALIGNBIT
9:
cbz DST_ALIGNBIT, 5f
mov TMP_D, DST0
tbz TMP_D, #0, 1f
lsr TMP_X, DATA1, #56
strb TMP_Xw, [TMP_D], #1
1:
tbz TMP_D, #1, 1f
lsr TMP_X, DATA1, #48
strh TMP_Xw, [TMP_D], #2
1:
tbz TMP_D, #2, 1f
lsr TMP_X, DATA1, #32
str TMP_Xw, [TMP_D], #4
1:
add DST, DST, #8
b 9f
5:
str DATA1, [DST], #8
9:
sub LEN, LEN, #8
add LEN, LEN, DST_ALIGNBIT, lsr #3
#endif
shifting_copy_loop:
ldp DATA1, DATA2, [SRC], #16
#if BYTE_ORDER == LITTLE_ENDIAN
lsr DATA0, DATA0, SRC_DST_ALIGNBIT
lsl TMP_X, DATA1, DST_SRC_ALIGNBIT
orr DATA0, DATA0, TMP_X
lsr DATA1, DATA1, SRC_DST_ALIGNBIT
lsl TMP_X, DATA2, DST_SRC_ALIGNBIT
orr DATA1, DATA1, TMP_X
#else
lsl DATA0, DATA0, SRC_DST_ALIGNBIT
lsr TMP_X, DATA1, DST_SRC_ALIGNBIT
orr DATA0, DATA0, TMP_X
lsl DATA1, DATA1, SRC_DST_ALIGNBIT
lsr TMP_X, DATA2, DST_SRC_ALIGNBIT
orr DATA1, DATA1, TMP_X
#endif
stp DATA0, DATA1, [DST], #16
mov DATA0, DATA2
sub LEN, LEN, #16
cmp LEN, #16
bhs shifting_copy_loop
tbz LEN, #3, 9f
ldr DATA1, [SRC], #8
#if BYTE_ORDER == LITTLE_ENDIAN
lsr DATA0, DATA0, SRC_DST_ALIGNBIT
lsl TMP_X, DATA1, DST_SRC_ALIGNBIT
orr DATA0, DATA0, TMP_X
#else
lsl DATA0, DATA0, SRC_DST_ALIGNBIT
lsr TMP_X, DATA1, DST_SRC_ALIGNBIT
orr DATA0, DATA0, TMP_X
#endif
str DATA0, [DST], #8
mov DATA0, DATA1
sub LEN, LEN, #8
9:
cbz LEN, shifting_copy_done
and TMP_X, DST_SRC_ALIGNBIT, #63
cmp LEN, TMP_X, lsr #3
bls 1f
ldr DATA1, [SRC], #8
1:
#if BYTE_ORDER == LITTLE_ENDIAN
lsr DATA0, DATA0, SRC_DST_ALIGNBIT
lsl TMP_X, DATA1, DST_SRC_ALIGNBIT
orr DATA0, DATA0, TMP_X
#else
lsl DATA0, DATA0, SRC_DST_ALIGNBIT
lsr TMP_X, DATA1, DST_SRC_ALIGNBIT
orr DATA0, DATA0, TMP_X
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
tbz LEN, #2, 1f
str DATA0w, [DST], #4
lsr DATA0, DATA0, #32
1:
tbz LEN, #1, 1f
strh DATA0w, [DST], #2
lsr DATA0, DATA0, #16
1:
tbz LEN, #0, 1f
strb DATA0w, [DST], #1
1:
#else
tbz LEN, #2, 1f
lsr TMP_X, DATA0, #32
str TMP_Xw, [DST], #4
1:
tbz LEN, #1, 1f
lsr TMP_X, DATA0, #16
strh TMP_Xw, [DST], #2
1:
tbz LEN, #0, 1f
lsr TMP_X, DATA0, #8
strb TMP_Xw, [DST], #1
1:
#endif
shifting_copy_done:
ret
#else
#ifndef NO_OVERLAP
cbz LEN, done
cmp SRC0, DST0
beq done
bcc backward_ignore_align
#endif
prfm PLDL1KEEP, [SRC0]
cmp LEN, #SMALLSIZE
bcs copy_forward
mov DST, DST0
copy_forward_small:
cmp LEN, #8
bcs 9f
tbz LEN, #2, 1f
ldr TMP_Xw, [SRC0], #4
str TMP_Xw, [DST], #4
1:
tbz LEN, #1, 1f
ldrh TMP_Xw, [SRC0], #2
strh TMP_Xw, [DST], #2
1:
tbz LEN, #0, 1f
ldrb TMP_Xw, [SRC0], #1
strb TMP_Xw, [DST], #1
1:
ret
9:
prfm PLDL1KEEP, [SRC0, #8]
cmp LEN, #16
bcs 9f
ldr TMP_X, [SRC0], #8
str TMP_X, [DST], #8
tbz LEN, #2, 1f
ldr TMP_Xw, [SRC0], #4
str TMP_Xw, [DST], #4
1:
tbz LEN, #1, 1f
ldrh TMP_Xw, [SRC0], #2
strh TMP_Xw, [DST], #2
1:
tbz LEN, #0, 1f
ldrb TMP_Xw, [SRC0], #1
strb TMP_Xw, [DST], #1
1:
ret
9:
prfm PLDL1KEEP, [SRC0, 16]
prfm PLDL1KEEP, [SRC0, 24]
ldp DATA0, DATA1, [SRC0], #16
stp DATA0, DATA1, [DST], #16
tbz LEN, #3, 1f
ldr TMP_X, [SRC0], #8
str TMP_X, [DST], #8
1:
tbz LEN, #2, 1f
ldr TMP_Xw, [SRC0], #4
str TMP_Xw, [DST], #4
1:
tbz LEN, #1, 1f
ldrh TMP_Xw, [SRC0], #2
strh TMP_Xw, [DST], #2
1:
tbz LEN, #0, 1f
ldrb TMP_Xw, [SRC0], #1
strb TMP_Xw, [DST], #1
1:
ret
#endif
.align 4
copy_forward:
mov DST, DST0
#ifndef STRICT_ALIGNMENT
cmp LEN, #512
bcc 9f
#endif
tbz DST, #0, 1f
ldrb TMP_Xw, [SRC0], #1
strb TMP_Xw, [DST], #1
sub LEN, LEN, #1
1:
tbz DST, #1, 1f
ldrh TMP_Xw, [SRC0], #2
strh TMP_Xw, [DST], #2
sub LEN, LEN, #2
1:
tbz DST, #2, 1f
ldr TMP_Xw, [SRC0], #4
str TMP_Xw, [DST], #4
sub LEN, LEN, #4
1:
#if (STP_ALIGN > 8)
tbz DST, #3, 1f
ldr TMP_X, [SRC0], #8
str TMP_X, [DST], #8
sub LEN, LEN, #8
1:
#endif
9:
forward_copy1k:
cmp LEN, #1024
blo 9f
1:
sub LEN, LEN, #1024
.rept (1024 / 16)
ldp DATA0, DATA1, [SRC0], #16
stp DATA0, DATA1, [DST], #16
.endr
cmp LEN, #1024
bhs 1b
9:
tbz LEN, #9, 1f
.rept (512 / 16)
ldp DATA0, DATA1, [SRC0], #16
stp DATA0, DATA1, [DST], #16
.endr
1:
tbz LEN, #8, 1f
.rept (256 / 16)
ldp DATA0, DATA1, [SRC0], #16
stp DATA0, DATA1, [DST], #16
.endr
1:
tbz LEN, #7, 1f
.rept (128 / 16)
ldp DATA0, DATA1, [SRC0], #16
stp DATA0, DATA1, [DST], #16
.endr
1:
tbz LEN, #6, 1f
.rept (64 / 16)
ldp DATA0, DATA1, [SRC0], #16
stp DATA0, DATA1, [DST], #16
.endr
1:
tbz LEN, #5, 1f
.rept (32 / 16)
ldp DATA0, DATA1, [SRC0], #16
stp DATA0, DATA1, [DST], #16
.endr
1:
tbz LEN, #4, 1f
ldp DATA0, DATA1, [SRC0], #16
stp DATA0, DATA1, [DST], #16
1:
tbz LEN, #3, 1f
ldr TMP_X, [SRC0], #8
str TMP_X, [DST], #8
1:
tbz LEN, #2, 1f
ldr TMP_Xw, [SRC0], #4
str TMP_Xw, [DST], #4
1:
tbz LEN, #1, 1f
ldrh TMP_Xw, [SRC0], #2
strh TMP_Xw, [DST], #2
1:
tbz LEN, #0, 1f
ldrb TMP_Xw, [SRC0], #1
strb TMP_Xw, [DST], #1
1:
done:
ret
END(FUNCTION)