1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006 Free Software Foundation, Inc.
* This file was originally part of the GNU C Library
* Contributed to glibc by MontaVista Software, Inc. (written by Nicolas Pitre)
* Adapted for Rockbox by Daniel Ankers
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
/*
* Endian independent macros for shifting bytes within registers.
*/
#ifndef __ARMEB__
#define pull lsr
#define push lsl
#else
#define pull lsl
#define push lsr
#endif
/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
.section .icode,"ax",%progbits
.align 2
.global memcpy
.type memcpy,%function
memcpy:
stmfd sp!, {r0, r4, lr}
subs r2, r2, #4
blt 8f
ands ip, r0, #3
bne 9f
ands ip, r1, #3
bne 10f
1: subs r2, r2, #(28)
stmfd sp!, {r5 - r8}
blt 5f
2:
3:
4: ldmia r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
subs r2, r2, #32
stmia r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
bge 3b
5: ands ip, r2, #28
rsb ip, ip, #32
addne pc, pc, ip @ C is always clear here
b 7f
6: nop
ldr r3, [r1], #4
ldr r4, [r1], #4
ldr r5, [r1], #4
ldr r6, [r1], #4
ldr r7, [r1], #4
ldr r8, [r1], #4
ldr lr, [r1], #4
add pc, pc, ip
nop
nop
str r3, [r0], #4
str r4, [r0], #4
str r5, [r0], #4
str r6, [r0], #4
str r7, [r0], #4
str r8, [r0], #4
str lr, [r0], #4
7: ldmfd sp!, {r5 - r8}
8: movs r2, r2, lsl #31
ldrneb r3, [r1], #1
ldrcsb r4, [r1], #1
ldrcsb ip, [r1]
strneb r3, [r0], #1
strcsb r4, [r0], #1
strcsb ip, [r0]
ldmfd sp!, {r0, r4, pc}
9: rsb ip, ip, #4
cmp ip, #2
ldrgtb r3, [r1], #1
ldrgeb r4, [r1], #1
ldrb lr, [r1], #1
strgtb r3, [r0], #1
strgeb r4, [r0], #1
subs r2, r2, ip
strb lr, [r0], #1
blt 8b
ands ip, r1, #3
beq 1b
10: bic r1, r1, #3
cmp ip, #2
ldr lr, [r1], #4
beq 17f
bgt 18f
.macro forward_copy_shift pull push
subs r2, r2, #28
blt 14f
11: stmfd sp!, {r5 - r9}
12:
13: ldmia r1!, {r4, r5, r6, r7}
mov r3, lr, pull #\pull
subs r2, r2, #32
ldmia r1!, {r8, r9, ip, lr}
orr r3, r3, r4, push #\push
mov r4, r4, pull #\pull
orr r4, r4, r5, push #\push
mov r5, r5, pull #\pull
orr r5, r5, r6, push #\push
mov r6, r6, pull #\pull
orr r6, r6, r7, push #\push
mov r7, r7, pull #\pull
orr r7, r7, r8, push #\push
mov r8, r8, pull #\pull
orr r8, r8, r9, push #\push
mov r9, r9, pull #\pull
orr r9, r9, ip, push #\push
mov ip, ip, pull #\pull
orr ip, ip, lr, push #\push
stmia r0!, {r3, r4, r5, r6, r7, r8, r9, ip}
bge 12b
ldmfd sp!, {r5 - r9}
14: ands ip, r2, #28
beq 16f
15: mov r3, lr, pull #\pull
ldr lr, [r1], #4
subs ip, ip, #4
orr r3, r3, lr, push #\push
str r3, [r0], #4
bgt 15b
16: sub r1, r1, #(\push / 8)
b 8b
.endm
forward_copy_shift pull=8 push=24
17: forward_copy_shift pull=16 push=16
18: forward_copy_shift pull=24 push=8
|