mb/google/zork: Move max98357a out of baseboard
[coreboot.git] / src / arch / arm / memcpy.S
blobd5e28ac147e9b192bf3782ca6d8be4d869a87950
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Based on linux/arch/arm/lib/memcpy.S
4  */
6 #include <arch/asm.h>
7 #include "asmlib.h"
9 #define LDR1W_SHIFT     0
10 #define STR1W_SHIFT     0
12         .macro ldr1w ptr reg abort
13         W(ldr) \reg, [\ptr], #4
14         .endm
16         .macro ldr4w ptr reg1 reg2 reg3 reg4 abort
17         ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4}
18         .endm
20         .macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
21         ldmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
22         .endm
24         .macro ldr1b ptr reg cond=al abort
25         ldr\cond\()b \reg, [\ptr], #1
26         .endm
28         .macro str1w ptr reg abort
29         W(str) \reg, [\ptr], #4
30         .endm
32         .macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
33         stmia \ptr!, {\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8}
34         .endm
36         .macro str1b ptr reg cond=al abort
37         str\cond\()b \reg, [\ptr], #1
38         .endm
40         .macro enter reg1 reg2
41         stmdb sp!, {r0, \reg1, \reg2}
42         .endm
44         .macro exit reg1 reg2
45         ldmfd sp!, {r0, \reg1, \reg2}
46         .endm
48 /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
50 ENTRY(memcpy)
52                 enter   r4, lr
54                 subs    r2, r2, #4
55                 blt     8f
56                 ands    ip, r0, #3
57         PLD(    pld     [r1, #0]                )
58                 bne     9f
59                 ands    ip, r1, #3
60                 bne     10f
62 1:              subs    r2, r2, #(28)
63                 stmfd   sp!, {r5 - r8}
64                 blt     5f
66         CALGN(  ands    ip, r0, #31             )
67         CALGN(  rsb     r3, ip, #32             )
68         CALGN(  sbcnes  r4, r3, r2              )  @ C is always set here
69         CALGN(  bcs     2f                      )
70         CALGN(  adr     r4, 6f                  )
71         CALGN(  subs    r2, r2, r3              )  @ C gets set
72         CALGN(  add     pc, r4, ip              )
74         PLD(    pld     [r1, #0]                )
75 2:      PLD(    subs    r2, r2, #96             )
76         PLD(    pld     [r1, #28]               )
77         PLD(    blt     4f                      )
78         PLD(    pld     [r1, #60]               )
79         PLD(    pld     [r1, #92]               )
81 3:      PLD(    pld     [r1, #124]              )
82 4:              ldr8w   r1, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f
83                 subs    r2, r2, #32
84                 str8w   r0, r3, r4, r5, r6, r7, r8, ip, lr, abort=20f
85                 bge     3b
86         PLD(    cmn     r2, #96                 )
87         PLD(    bge     4b                      )
89 5:              ands    ip, r2, #28
90                 rsb     ip, ip, #32
91 #if LDR1W_SHIFT > 0
92                 lsl     ip, ip, #LDR1W_SHIFT
93 #endif
94                 addne   pc, pc, ip              @ C is always clear here
95                 b       7f
97                 .rept   (1 << LDR1W_SHIFT)
98                 W(nop)
99                 .endr
100                 ldr1w   r1, r3, abort=20f
101                 ldr1w   r1, r4, abort=20f
102                 ldr1w   r1, r5, abort=20f
103                 ldr1w   r1, r6, abort=20f
104                 ldr1w   r1, r7, abort=20f
105                 ldr1w   r1, r8, abort=20f
106                 ldr1w   r1, lr, abort=20f
108 #if LDR1W_SHIFT < STR1W_SHIFT
109                 lsl     ip, ip, #STR1W_SHIFT - LDR1W_SHIFT
110 #elif LDR1W_SHIFT > STR1W_SHIFT
111                 lsr     ip, ip, #LDR1W_SHIFT - STR1W_SHIFT
112 #endif
113                 add     pc, pc, ip
114                 nop
115                 .rept   (1 << STR1W_SHIFT)
116                 W(nop)
117                 .endr
118                 str1w   r0, r3, abort=20f
119                 str1w   r0, r4, abort=20f
120                 str1w   r0, r5, abort=20f
121                 str1w   r0, r6, abort=20f
122                 str1w   r0, r7, abort=20f
123                 str1w   r0, r8, abort=20f
124                 str1w   r0, lr, abort=20f
126         CALGN(  bcs     2b                      )
128 7:              ldmfd   sp!, {r5 - r8}
130 8:              movs    r2, r2, lsl #31
131                 ldr1b   r1, r3, ne, abort=21f
132                 ldr1b   r1, r4, cs, abort=21f
133                 ldr1b   r1, ip, cs, abort=21f
134                 str1b   r0, r3, ne, abort=21f
135                 str1b   r0, r4, cs, abort=21f
136                 str1b   r0, ip, cs, abort=21f
138                 exit    r4, pc
140 9:              rsb     ip, ip, #4
141                 cmp     ip, #2
142                 ldr1b   r1, r3, gt, abort=21f
143                 ldr1b   r1, r4, ge, abort=21f
144                 ldr1b   r1, lr, abort=21f
145                 str1b   r0, r3, gt, abort=21f
146                 str1b   r0, r4, ge, abort=21f
147                 subs    r2, r2, ip
148                 str1b   r0, lr, abort=21f
149                 blt     8b
150                 ands    ip, r1, #3
151                 beq     1b
153 10:             bic     r1, r1, #3
154                 cmp     ip, #2
155                 ldr1w   r1, lr, abort=21f
156                 beq     17f
157                 bgt     18f
160                 .macro  forward_copy_shift pull push
162                 subs    r2, r2, #28
163                 blt     14f
165         CALGN(  ands    ip, r0, #31             )
166         CALGN(  rsb     ip, ip, #32             )
167         CALGN(  sbcnes  r4, ip, r2              )  @ C is always set here
168         CALGN(  subcc   r2, r2, ip              )
169         CALGN(  bcc     15f                     )
171 11:             stmfd   sp!, {r5 - r9}
173         PLD(    pld     [r1, #0]                )
174         PLD(    subs    r2, r2, #96             )
175         PLD(    pld     [r1, #28]               )
176         PLD(    blt     13f                     )
177         PLD(    pld     [r1, #60]               )
178         PLD(    pld     [r1, #92]               )
180 12:     PLD(    pld     [r1, #124]              )
181 13:             ldr4w   r1, r4, r5, r6, r7, abort=19f
182                 mov     r3, lr, pull #\pull
183                 subs    r2, r2, #32
184                 ldr4w   r1, r8, r9, ip, lr, abort=19f
185                 orr     r3, r3, r4, push #\push
186                 mov     r4, r4, pull #\pull
187                 orr     r4, r4, r5, push #\push
188                 mov     r5, r5, pull #\pull
189                 orr     r5, r5, r6, push #\push
190                 mov     r6, r6, pull #\pull
191                 orr     r6, r6, r7, push #\push
192                 mov     r7, r7, pull #\pull
193                 orr     r7, r7, r8, push #\push
194                 mov     r8, r8, pull #\pull
195                 orr     r8, r8, r9, push #\push
196                 mov     r9, r9, pull #\pull
197                 orr     r9, r9, ip, push #\push
198                 mov     ip, ip, pull #\pull
199                 orr     ip, ip, lr, push #\push
200                 str8w   r0, r3, r4, r5, r6, r7, r8, r9, ip, , abort=19f
201                 bge     12b
202         PLD(    cmn     r2, #96                 )
203         PLD(    bge     13b                     )
205                 ldmfd   sp!, {r5 - r9}
207 14:             ands    ip, r2, #28
208                 beq     16f
210 15:             mov     r3, lr, pull #\pull
211                 ldr1w   r1, lr, abort=21f
212                 subs    ip, ip, #4
213                 orr     r3, r3, lr, push #\push
214                 str1w   r0, r3, abort=21f
215                 bgt     15b
216         CALGN(  cmp     r2, #0                  )
217         CALGN(  bge     11b                     )
219 16:             sub     r1, r1, #(\push / 8)
220                 b       8b
222                 .endm
225                 forward_copy_shift      pull=8  push=24
227 17:             forward_copy_shift      pull=16 push=16
229 18:             forward_copy_shift      pull=24 push=8
230 ENDPROC(memcpy)