Merge branch 'master' of git://git.denx.de/u-boot-arm
[platform/kernel/u-boot.git] / arch / arm / lib / memcpy.S
1 /*
2  *  linux/arch/arm/lib/memcpy.S
3  *
4  *  Author:     Nicolas Pitre
5  *  Created:    Sep 28, 2005
6  *  Copyright:  MontaVista Software, Inc.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License version 2 as
10  *  published by the Free Software Foundation.
11  */
12
13 #include <asm/assembler.h>
14
15 #define W(instr)        instr
16
17 #define LDR1W_SHIFT     0
18 #define STR1W_SHIFT     0
19
20         .macro ldr1w ptr reg abort
21         W(ldr) \reg, [\ptr], #4
22         .endm
23
24         .macro ldr4w ptr reg1 reg2 reg3 reg4 abort
25         ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4}
26         .endm
27
28         .macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
29         ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
30         .endm
31
32         .macro ldr1b ptr reg cond=al abort
33         ldr\cond\()b \reg, [\ptr], #1
34         .endm
35
36         .macro str1w ptr reg abort
37         W(str) \reg, [\ptr], #4
38         .endm
39
40         .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
41         stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
42         .endm
43
44         .macro str1b ptr reg cond=al abort
45         str\cond\()b \reg, [\ptr], #1
46         .endm
47
48         .macro enter reg1 reg2
49         stmdb sp!, {r0, \reg1, \reg2}
50         .endm
51
52         .macro exit reg1 reg2
53         ldmfd sp!, {r0, \reg1, \reg2}
54         .endm
55
56         .text
57
58 /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
59
60 .globl memcpy
61 memcpy:
62
63                 cmp     r0, r1
64                 moveq   pc, lr
65
66                 enter   r4, lr
67
68                 subs    r2, r2, #4
69                 blt     8f
70                 ands    ip, r0, #3
71         PLD(    pld     [r1, #0]                )
72                 bne     9f
73                 ands    ip, r1, #3
74                 bne     10f
75
76 1:              subs    r2, r2, #(28)
77                 stmfd   sp!, {r5 - r8}
78                 blt     5f
79
80         CALGN(  ands    ip, r0, #31             )
81         CALGN(  rsb     r3, ip, #32             )
82         CALGN(  sbcnes  r4, r3, r2              )  @ C is always set here
83         CALGN(  bcs     2f                      )
84         CALGN(  adr     r4, 6f                  )
85         CALGN(  subs    r2, r2, r3              )  @ C gets set
86         CALGN(  add     pc, r4, ip              )
87
88         PLD(    pld     [r1, #0]                )
89 2:      PLD(    subs    r2, r2, #96             )
90         PLD(    pld     [r1, #28]               )
91         PLD(    blt     4f                      )
92         PLD(    pld     [r1, #60]               )
93         PLD(    pld     [r1, #92]               )
94
95 3:      PLD(    pld     [r1, #124]              )
96 4:              ldr8w   r1, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f
97                 subs    r2, r2, #32
98                 str8w   r0, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f
99                 bge     3b
100         PLD(    cmn     r2, #96                 )
101         PLD(    bge     4b                      )
102
103 5:              ands    ip, r2, #28
104                 rsb     ip, ip, #32
105 #if LDR1W_SHIFT > 0
106                 lsl     ip, ip, #LDR1W_SHIFT
107 #endif
108                 addne   pc, pc, ip              @ C is always clear here
109                 b       7f
110 6:
111                 .rept   (1 << LDR1W_SHIFT)
112                 W(nop)
113                 .endr
114                 ldr1w   r1, r3, abort=20f
115                 ldr1w   r1, r4, abort=20f
116                 ldr1w   r1, r5, abort=20f
117                 ldr1w   r1, r6, abort=20f
118                 ldr1w   r1, r7, abort=20f
119                 ldr1w   r1, r8, abort=20f
120                 ldr1w   r1, lr, abort=20f
121
122 #if LDR1W_SHIFT < STR1W_SHIFT
123                 lsl     ip, ip, #STR1W_SHIFT - LDR1W_SHIFT
124 #elif LDR1W_SHIFT > STR1W_SHIFT
125                 lsr     ip, ip, #LDR1W_SHIFT - STR1W_SHIFT
126 #endif
127                 add     pc, pc, ip
128                 nop
129                 .rept   (1 << STR1W_SHIFT)
130                 W(nop)
131                 .endr
132                 str1w   r0, r3, abort=20f
133                 str1w   r0, r4, abort=20f
134                 str1w   r0, r5, abort=20f
135                 str1w   r0, r6, abort=20f
136                 str1w   r0, r7, abort=20f
137                 str1w   r0, r8, abort=20f
138                 str1w   r0, lr, abort=20f
139
140         CALGN(  bcs     2b                      )
141
142 7:              ldmfd   sp!, {r5 - r8}
143
144 8:              movs    r2, r2, lsl #31
145                 ldr1b   r1, r3, ne, abort=21f
146                 ldr1b   r1, r4, cs, abort=21f
147                 ldr1b   r1, ip, cs, abort=21f
148                 str1b   r0, r3, ne, abort=21f
149                 str1b   r0, r4, cs, abort=21f
150                 str1b   r0, ip, cs, abort=21f
151
152                 exit    r4, pc
153
154 9:              rsb     ip, ip, #4
155                 cmp     ip, #2
156                 ldr1b   r1, r3, gt, abort=21f
157                 ldr1b   r1, r4, ge, abort=21f
158                 ldr1b   r1, lr, abort=21f
159                 str1b   r0, r3, gt, abort=21f
160                 str1b   r0, r4, ge, abort=21f
161                 subs    r2, r2, ip
162                 str1b   r0, lr, abort=21f
163                 blt     8b
164                 ands    ip, r1, #3
165                 beq     1b
166
167 10:             bic     r1, r1, #3
168                 cmp     ip, #2
169                 ldr1w   r1, lr, abort=21f
170                 beq     17f
171                 bgt     18f
172
173
174                 .macro  forward_copy_shift pull push
175
176                 subs    r2, r2, #28
177                 blt     14f
178
179         CALGN(  ands    ip, r0, #31             )
180         CALGN(  rsb     ip, ip, #32             )
181         CALGN(  sbcnes  r4, ip, r2              )  @ C is always set here
182         CALGN(  subcc   r2, r2, ip              )
183         CALGN(  bcc     15f                     )
184
185 11:             stmfd   sp!, {r5 - r9}
186
187         PLD(    pld     [r1, #0]                )
188         PLD(    subs    r2, r2, #96             )
189         PLD(    pld     [r1, #28]               )
190         PLD(    blt     13f                     )
191         PLD(    pld     [r1, #60]               )
192         PLD(    pld     [r1, #92]               )
193
194 12:     PLD(    pld     [r1, #124]              )
195 13:             ldr4w   r1, r4, r5, r6, r7, abort=19f
196                 mov     r3, lr, pull #\pull
197                 subs    r2, r2, #32
198                 ldr4w   r1, r8, r9, ip, lr, abort=19f
199                 orr     r3, r3, r4, push #\push
200                 mov     r4, r4, pull #\pull
201                 orr     r4, r4, r5, push #\push
202                 mov     r5, r5, pull #\pull
203                 orr     r5, r5, r6, push #\push
204                 mov     r6, r6, pull #\pull
205                 orr     r6, r6, r7, push #\push
206                 mov     r7, r7, pull #\pull
207                 orr     r7, r7, r8, push #\push
208                 mov     r8, r8, pull #\pull
209                 orr     r8, r8, r9, push #\push
210                 mov     r9, r9, pull #\pull
211                 orr     r9, r9, ip, push #\push
212                 mov     ip, ip, pull #\pull
213                 orr     ip, ip, lr, push #\push
214                 str8w   r0, r3, r4, r5, r6, r7, r8, r9, ip, , abort=19f
215                 bge     12b
216         PLD(    cmn     r2, #96                 )
217         PLD(    bge     13b                     )
218
219                 ldmfd   sp!, {r5 - r9}
220
221 14:             ands    ip, r2, #28
222                 beq     16f
223
224 15:             mov     r3, lr, pull #\pull
225                 ldr1w   r1, lr, abort=21f
226                 subs    ip, ip, #4
227                 orr     r3, r3, lr, push #\push
228                 str1w   r0, r3, abort=21f
229                 bgt     15b
230         CALGN(  cmp     r2, #0                  )
231         CALGN(  bge     11b                     )
232
233 16:             sub     r1, r1, #(\push / 8)
234                 b       8b
235
236                 .endm
237
238
239                 forward_copy_shift      pull=8  push=24
240
241 17:             forward_copy_shift      pull=16 push=16
242
243 18:             forward_copy_shift      pull=24 push=8