hc
2023-11-22 983d7f83616922a6439b4352d1b3af488ee27f95
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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/*
 * linux/arch/unicore32/lib/copy_template.S
 *
 * Code specific to PKUnity SoC and UniCore ISA
 *
 * Copyright (C) 2001-2010 GUAN Xue-tao
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
 
/*
 * Theory of operation
 * -------------------
 *
 * This file provides the core code for a forward memory copy used in
 * the implementation of memcopy(), copy_to_user() and copy_from_user().
 *
 * The including file must define the following accessor macros
 * according to the need of the given function:
 *
 * ldr1w ptr reg abort
 *
 *    This loads one word from 'ptr', stores it in 'reg' and increments
 *    'ptr' to the next word. The 'abort' argument is used for fixup tables.
 *
 * ldr4w ptr reg1 reg2 reg3 reg4 abort
 * ldr8w ptr, reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
 *
 *    This loads four or eight words starting from 'ptr', stores them
 *    in provided registers and increments 'ptr' past those words.
 *    The'abort' argument is used for fixup tables.
 *
 * ldr1b ptr reg cond abort
 *
 *    Similar to ldr1w, but it loads a byte and increments 'ptr' one byte.
 *    It also must apply the condition code if provided, otherwise the
 *    "al" condition is assumed by default.
 *
 * str1w ptr reg abort
 * str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
 * str1b ptr reg cond abort
 *
 *    Same as their ldr* counterparts, but data is stored to 'ptr' location
 *    rather than being loaded.
 *
 * enter
 *
 *    Preserve the provided registers on the stack plus any additional
 *    data as needed by the implementation including this code. Called
 *    upon code entry.
 *
 * exit
 *
 *    Restore registers with the values previously saved with the
 *    'preserv' macro. Called upon code termination.
 */
 
 
       enter
 
       sub.a    r2, r2, #4
       bsl    8f
       and.a    ip, r0, #3
       bne    9f
       and.a    ip, r1, #3
       bne    10f
 
1:        sub.a    r2, r2, #(28)
       stm.w    (r5 - r8), [sp-]
       bsl    5f
 
3:
4:        ldr8w    r1, r3, r4, r5, r6, r7, r8, r10, r11, abort=20f
       sub.a    r2, r2, #32
       str8w    r0, r3, r4, r5, r6, r7, r8, r10, r11, abort=20f
       beg    3b
 
5:        and.a    ip, r2, #28
       rsub    ip, ip, #32
       beq    7f
       add    pc, pc, ip        @ C is always clear here
       nop
 
       ldr1w    r1, r3, abort=20f
       ldr1w    r1, r4, abort=20f
       ldr1w    r1, r5, abort=20f
       ldr1w    r1, r6, abort=20f
       ldr1w    r1, r7, abort=20f
       ldr1w    r1, r8, abort=20f
       ldr1w    r1, r11, abort=20f
 
       add    pc, pc, ip
       nop
 
       str1w    r0, r3, abort=20f
       str1w    r0, r4, abort=20f
       str1w    r0, r5, abort=20f
       str1w    r0, r6, abort=20f
       str1w    r0, r7, abort=20f
       str1w    r0, r8, abort=20f
       str1w    r0, r11, abort=20f
 
7:        ldm.w    (r5 - r8), [sp]+
 
8:        mov.a    r2, r2 << #31
       ldr1b    r1, r3, ne, abort=21f
       ldr1b    r1, r4, ea, abort=21f
       ldr1b    r1, r10, ea, abort=21f
       str1b    r0, r3, ne, abort=21f
       str1b    r0, r4, ea, abort=21f
       str1b    r0, r10, ea, abort=21f
 
       exit
 
9:        rsub    ip, ip, #4
       csub.a    ip, #2
       ldr1b    r1, r3, sg, abort=21f
       ldr1b    r1, r4, eg, abort=21f
       ldr1b    r1, r11, abort=21f
       str1b    r0, r3, sg, abort=21f
       str1b    r0, r4, eg, abort=21f
       sub.a    r2, r2, ip
       str1b    r0, r11, abort=21f
       bsl    8b
       and.a    ip, r1, #3
       beq    1b
 
10:        andn    r1, r1, #3
       csub.a    ip, #2
       ldr1w    r1, r11, abort=21f
       beq    17f
       bsg    18f
 
 
       .macro    forward_copy_shift a b
 
       sub.a    r2, r2, #28
       bsl    14f
 
11:        stm.w    (r5 - r9), [sp-]
 
12:
       ldr4w    r1, r4, r5, r6, r7, abort=19f
       mov    r3, r11 pull #\a
       sub.a    r2, r2, #32
       ldr4w    r1, r8, r9, r10, r11, abort=19f
       or    r3, r3, r4 push #\b
       mov    r4, r4 pull #\a
       or    r4, r4, r5 push #\b
       mov    r5, r5 pull #\a
       or    r5, r5, r6 push #\b
       mov    r6, r6 pull #\a
       or    r6, r6, r7 push #\b
       mov    r7, r7 pull #\a
       or    r7, r7, r8 push #\b
       mov    r8, r8 pull #\a
       or    r8, r8, r9 push #\b
       mov    r9, r9 pull #\a
       or    r9, r9, r10 push #\b
       mov    r10, r10 pull #\a
       or    r10, r10, r11 push #\b
       str8w    r0, r3, r4, r5, r6, r7, r8, r9, r10, , abort=19f
       beg    12b
 
       ldm.w    (r5 - r9), [sp]+
 
14:        and.a    ip, r2, #28
       beq    16f
 
15:        mov    r3, r11 pull #\a
       ldr1w    r1, r11, abort=21f
       sub.a    ip, ip, #4
       or    r3, r3, r11 push #\b
       str1w    r0, r3, abort=21f
       bsg    15b
 
16:        sub    r1, r1, #(\b / 8)
       b    8b
 
       .endm
 
 
       forward_copy_shift    a=8    b=24
 
17:        forward_copy_shift    a=16    b=16
 
18:        forward_copy_shift    a=24    b=8
 
 
/*
 * Abort preamble and completion macros.
 * If a fixup handler is required then those macros must surround it.
 * It is assumed that the fixup code will handle the private part of
 * the exit macro.
 */
 
   .macro    copy_abort_preamble
19:    ldm.w    (r5 - r9), [sp]+
   b    21f
299:    .word    0            @ store lr
                   @ to avoid function call in fixup
20:    ldm.w    (r5 - r8), [sp]+
21:
   adr    r1, 299b
   stw    lr, [r1]
   .endm
 
   .macro    copy_abort_end
   adr    lr, 299b
   ldw    pc, [lr]
   .endm