copy_template.S
4.57 KB
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
214
/*
* 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