]> git.sur5r.net Git - u-boot/blob - arch/arm/lib/memcpy.S
SPDX: Convert all of our single license tags to Linux Kernel style
[u-boot] / arch / arm / lib / memcpy.S
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  *  linux/arch/arm/lib/memcpy.S
4  *
5  *  Author:     Nicolas Pitre
6  *  Created:    Sep 28, 2005
7  *  Copyright:  MontaVista Software, Inc.
8  */
9
10 #include <linux/linkage.h>
11 #include <asm/assembler.h>
12
13 #define LDR1W_SHIFT     0
14 #define STR1W_SHIFT     0
15
16         .macro ldr1w ptr reg abort
17         W(ldr) \reg, [\ptr], #4
18         .endm
19
20         .macro ldr4w ptr reg1 reg2 reg3 reg4 abort
21         ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4}
22         .endm
23
24         .macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
25         ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
26         .endm
27
28         .macro ldr1b ptr reg cond=al abort
29         ldrb\cond\() \reg, [\ptr], #1
30         .endm
31
32         .macro str1w ptr reg abort
33         W(str) \reg, [\ptr], #4
34         .endm
35
36         .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
37         stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
38         .endm
39
40         .macro str1b ptr reg cond=al abort
41         strb\cond\() \reg, [\ptr], #1
42         .endm
43
44         .macro enter reg1 reg2
45         stmdb sp!, {r0, \reg1, \reg2}
46         .endm
47
48         .macro exit reg1 reg2
49         ldmfd sp!, {r0, \reg1, \reg2}
50         .endm
51
52         .text
53
54 /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
55         .syntax unified
56 #if CONFIG_IS_ENABLED(SYS_THUMB_BUILD) && !defined(MEMCPY_NO_THUMB_BUILD)
57         .thumb
58         .thumb_func
59 #endif
60 ENTRY(memcpy)
61                 cmp     r0, r1
62                 moveq   pc, lr
63
64                 enter   r4, lr
65
66                 subs    r2, r2, #4
67                 blt     8f
68                 ands    ip, r0, #3
69         PLD(    pld     [r1, #0]                )
70                 bne     9f
71                 ands    ip, r1, #3
72                 bne     10f
73
74 1:              subs    r2, r2, #(28)
75                 stmfd   sp!, {r5 - r8}
76                 blt     5f
77
78         CALGN(  ands    ip, r0, #31             )
79         CALGN(  rsb     r3, ip, #32             )
80         CALGN(  sbcsne  r4, r3, r2              )  @ C is always set here
81         CALGN(  bcs     2f                      )
82         CALGN(  adr     r4, 6f                  )
83         CALGN(  subs    r2, r2, r3              )  @ C gets set
84         CALGN(  add     pc, r4, ip              )
85
86         PLD(    pld     [r1, #0]                )
87 2:      PLD(    subs    r2, r2, #96             )
88         PLD(    pld     [r1, #28]               )
89         PLD(    blt     4f                      )
90         PLD(    pld     [r1, #60]               )
91         PLD(    pld     [r1, #92]               )
92
93 3:      PLD(    pld     [r1, #124]              )
94 4:              ldr8w   r1, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f
95                 subs    r2, r2, #32
96                 str8w   r0, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f
97                 bge     3b
98         PLD(    cmn     r2, #96                 )
99         PLD(    bge     4b                      )
100
101 5:              ands    ip, r2, #28
102                 rsb     ip, ip, #32
103 #if LDR1W_SHIFT > 0
104                 lsl     ip, ip, #LDR1W_SHIFT
105 #endif
106                 addne   pc, pc, ip              @ C is always clear here
107                 b       7f
108 6:
109                 .rept   (1 << LDR1W_SHIFT)
110                 W(nop)
111                 .endr
112                 ldr1w   r1, r3, abort=20f
113                 ldr1w   r1, r4, abort=20f
114                 ldr1w   r1, r5, abort=20f
115                 ldr1w   r1, r6, abort=20f
116                 ldr1w   r1, r7, abort=20f
117                 ldr1w   r1, r8, abort=20f
118                 ldr1w   r1, lr, abort=20f
119
120 #if LDR1W_SHIFT < STR1W_SHIFT
121                 lsl     ip, ip, #STR1W_SHIFT - LDR1W_SHIFT
122 #elif LDR1W_SHIFT > STR1W_SHIFT
123                 lsr     ip, ip, #LDR1W_SHIFT - STR1W_SHIFT
124 #endif
125                 add     pc, pc, ip
126                 nop
127                 .rept   (1 << STR1W_SHIFT)
128                 W(nop)
129                 .endr
130                 str1w   r0, r3, abort=20f
131                 str1w   r0, r4, abort=20f
132                 str1w   r0, r5, abort=20f
133                 str1w   r0, r6, abort=20f
134                 str1w   r0, r7, abort=20f
135                 str1w   r0, r8, abort=20f
136                 str1w   r0, lr, abort=20f
137
138         CALGN(  bcs     2b                      )
139
140 7:              ldmfd   sp!, {r5 - r8}
141
142 8:              movs    r2, r2, lsl #31
143                 ldr1b   r1, r3, ne, abort=21f
144                 ldr1b   r1, r4, cs, abort=21f
145                 ldr1b   r1, ip, cs, abort=21f
146                 str1b   r0, r3, ne, abort=21f
147                 str1b   r0, r4, cs, abort=21f
148                 str1b   r0, ip, cs, abort=21f
149
150                 exit    r4, pc
151
152 9:              rsb     ip, ip, #4
153                 cmp     ip, #2
154                 ldr1b   r1, r3, gt, abort=21f
155                 ldr1b   r1, r4, ge, abort=21f
156                 ldr1b   r1, lr, abort=21f
157                 str1b   r0, r3, gt, abort=21f
158                 str1b   r0, r4, ge, abort=21f
159                 subs    r2, r2, ip
160                 str1b   r0, lr, abort=21f
161                 blt     8b
162                 ands    ip, r1, #3
163                 beq     1b
164
165 10:             bic     r1, r1, #3
166                 cmp     ip, #2
167                 ldr1w   r1, lr, abort=21f
168                 beq     17f
169                 bgt     18f
170
171
172                 .macro  forward_copy_shift pull push
173
174                 subs    r2, r2, #28
175                 blt     14f
176
177         CALGN(  ands    ip, r0, #31             )
178         CALGN(  rsb     ip, ip, #32             )
179         CALGN(  sbcsne  r4, ip, r2              )  @ C is always set here
180         CALGN(  subcc   r2, r2, ip              )
181         CALGN(  bcc     15f                     )
182
183 11:             stmfd   sp!, {r5 - r9}
184
185         PLD(    pld     [r1, #0]                )
186         PLD(    subs    r2, r2, #96             )
187         PLD(    pld     [r1, #28]               )
188         PLD(    blt     13f                     )
189         PLD(    pld     [r1, #60]               )
190         PLD(    pld     [r1, #92]               )
191
192 12:     PLD(    pld     [r1, #124]              )
193 13:             ldr4w   r1, r4, r5, r6, r7, abort=19f
194                 mov     r3, lr, lspull #\pull
195                 subs    r2, r2, #32
196                 ldr4w   r1, r8, r9, ip, lr, abort=19f
197                 orr     r3, r3, r4, lspush #\push
198                 mov     r4, r4, lspull #\pull
199                 orr     r4, r4, r5, lspush #\push
200                 mov     r5, r5, lspull #\pull
201                 orr     r5, r5, r6, lspush #\push
202                 mov     r6, r6, lspull #\pull
203                 orr     r6, r6, r7, lspush #\push
204                 mov     r7, r7, lspull #\pull
205                 orr     r7, r7, r8, lspush #\push
206                 mov     r8, r8, lspull #\pull
207                 orr     r8, r8, r9, lspush #\push
208                 mov     r9, r9, lspull #\pull
209                 orr     r9, r9, ip, lspush #\push
210                 mov     ip, ip, lspull #\pull
211                 orr     ip, ip, lr, lspush #\push
212                 str8w   r0, r3, r4, r5, r6, r7, r8, r9, ip, , abort=19f
213                 bge     12b
214         PLD(    cmn     r2, #96                 )
215         PLD(    bge     13b                     )
216
217                 ldmfd   sp!, {r5 - r9}
218
219 14:             ands    ip, r2, #28
220                 beq     16f
221
222 15:             mov     r3, lr, lspull #\pull
223                 ldr1w   r1, lr, abort=21f
224                 subs    ip, ip, #4
225                 orr     r3, r3, lr, lspush #\push
226                 str1w   r0, r3, abort=21f
227                 bgt     15b
228         CALGN(  cmp     r2, #0                  )
229         CALGN(  bge     11b                     )
230
231 16:             sub     r1, r1, #(\push / 8)
232                 b       8b
233
234                 .endm
235
236
237                 forward_copy_shift      pull=8  push=24
238
239 17:             forward_copy_shift      pull=16 push=16
240
241 18:             forward_copy_shift      pull=24 push=8
242
243
244 /*
245  * Abort preamble and completion macros.
246  * If a fixup handler is required then those macros must surround it.
247  * It is assumed that the fixup code will handle the private part of
248  * the exit macro.
249  */
250
251         .macro  copy_abort_preamble
252 19:     ldmfd   sp!, {r5 - r9}
253         b       21f
254 20:     ldmfd   sp!, {r5 - r8}
255 21:
256         .endm
257
258         .macro  copy_abort_end
259         ldmfd   sp!, {r4, pc}
260         .endm
261
262 ENDPROC(memcpy)