blob: b48bd6d5fd83144ca4705becef558faadb33f725 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/arch/arm/lib/uaccess.S
3 *
4 * Copyright (C) 1995, 1996,1997,1998 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Routines to block copy data to/from user memory
11 * These are highly optimised both for the 4k page size
12 * and for various alignments.
13 */
14#include <linux/linkage.h>
15#include <asm/assembler.h>
16#include <asm/errno.h>
17
18 .text
19
20#define PAGE_SHIFT 12
21
Russell King02fcb972006-06-21 14:44:52 +010022/* Prototype: int __copy_to_user(void *to, const char *from, size_t n)
Linus Torvalds1da177e2005-04-16 15:20:36 -070023 * Purpose : copy a block to user memory from kernel memory
24 * Params : to - user memory
25 * : from - kernel memory
26 * : n - number of bytes to copy
27 * Returns : Number of bytes NOT copied.
28 */
29
Nicolas Pitre7ba11a92005-11-11 21:51:47 +000030.Lc2u_dest_not_aligned:
Linus Torvalds1da177e2005-04-16 15:20:36 -070031 rsb ip, ip, #4
32 cmp ip, #2
33 ldrb r3, [r1], #1
34USER( strbt r3, [r0], #1) @ May fault
35 ldrgeb r3, [r1], #1
36USER( strgebt r3, [r0], #1) @ May fault
37 ldrgtb r3, [r1], #1
38USER( strgtbt r3, [r0], #1) @ May fault
39 sub r2, r2, ip
Nicolas Pitre7ba11a92005-11-11 21:51:47 +000040 b .Lc2u_dest_aligned
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
Russell King02fcb972006-06-21 14:44:52 +010042ENTRY(__copy_to_user)
Linus Torvalds1da177e2005-04-16 15:20:36 -070043 stmfd sp!, {r2, r4 - r7, lr}
44 cmp r2, #4
Nicolas Pitre7ba11a92005-11-11 21:51:47 +000045 blt .Lc2u_not_enough
Linus Torvalds1da177e2005-04-16 15:20:36 -070046 ands ip, r0, #3
Nicolas Pitre7ba11a92005-11-11 21:51:47 +000047 bne .Lc2u_dest_not_aligned
48.Lc2u_dest_aligned:
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
50 ands ip, r1, #3
Nicolas Pitre7ba11a92005-11-11 21:51:47 +000051 bne .Lc2u_src_not_aligned
Linus Torvalds1da177e2005-04-16 15:20:36 -070052/*
53 * Seeing as there has to be at least 8 bytes to copy, we can
54 * copy one word, and force a user-mode page fault...
55 */
56
Nicolas Pitre7ba11a92005-11-11 21:51:47 +000057.Lc2u_0fupi: subs r2, r2, #4
Linus Torvalds1da177e2005-04-16 15:20:36 -070058 addmi ip, r2, #4
Nicolas Pitre7ba11a92005-11-11 21:51:47 +000059 bmi .Lc2u_0nowords
Linus Torvalds1da177e2005-04-16 15:20:36 -070060 ldr r3, [r1], #4
61USER( strt r3, [r0], #4) @ May fault
62 mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
63 rsb ip, ip, #0
64 movs ip, ip, lsr #32 - PAGE_SHIFT
Nicolas Pitre7ba11a92005-11-11 21:51:47 +000065 beq .Lc2u_0fupi
Linus Torvalds1da177e2005-04-16 15:20:36 -070066/*
67 * ip = max no. of bytes to copy before needing another "strt" insn
68 */
69 cmp r2, ip
70 movlt ip, r2
71 sub r2, r2, ip
72 subs ip, ip, #32
Nicolas Pitre7ba11a92005-11-11 21:51:47 +000073 blt .Lc2u_0rem8lp
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Nicolas Pitre7ba11a92005-11-11 21:51:47 +000075.Lc2u_0cpy8lp: ldmia r1!, {r3 - r6}
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 stmia r0!, {r3 - r6} @ Shouldnt fault
77 ldmia r1!, {r3 - r6}
78 subs ip, ip, #32
79 stmia r0!, {r3 - r6} @ Shouldnt fault
Nicolas Pitre7ba11a92005-11-11 21:51:47 +000080 bpl .Lc2u_0cpy8lp
Linus Torvalds1da177e2005-04-16 15:20:36 -070081
Nicolas Pitre7ba11a92005-11-11 21:51:47 +000082.Lc2u_0rem8lp: cmn ip, #16
Linus Torvalds1da177e2005-04-16 15:20:36 -070083 ldmgeia r1!, {r3 - r6}
84 stmgeia r0!, {r3 - r6} @ Shouldnt fault
85 tst ip, #8
86 ldmneia r1!, {r3 - r4}
87 stmneia r0!, {r3 - r4} @ Shouldnt fault
88 tst ip, #4
89 ldrne r3, [r1], #4
90 strnet r3, [r0], #4 @ Shouldnt fault
91 ands ip, ip, #3
Nicolas Pitre7ba11a92005-11-11 21:51:47 +000092 beq .Lc2u_0fupi
93.Lc2u_0nowords: teq ip, #0
94 beq .Lc2u_finished
95.Lc2u_nowords: cmp ip, #2
Linus Torvalds1da177e2005-04-16 15:20:36 -070096 ldrb r3, [r1], #1
97USER( strbt r3, [r0], #1) @ May fault
98 ldrgeb r3, [r1], #1
99USER( strgebt r3, [r0], #1) @ May fault
100 ldrgtb r3, [r1], #1
101USER( strgtbt r3, [r0], #1) @ May fault
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000102 b .Lc2u_finished
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000104.Lc2u_not_enough:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 movs ip, r2
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000106 bne .Lc2u_nowords
107.Lc2u_finished: mov r0, #0
Russell King1b93a712006-06-25 11:23:45 +0100108 ldmfd sp!, {r2, r4 - r7, pc}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000110.Lc2u_src_not_aligned:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 bic r1, r1, #3
112 ldr r7, [r1], #4
113 cmp ip, #2
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000114 bgt .Lc2u_3fupi
115 beq .Lc2u_2fupi
116.Lc2u_1fupi: subs r2, r2, #4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 addmi ip, r2, #4
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000118 bmi .Lc2u_1nowords
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119 mov r3, r7, pull #8
120 ldr r7, [r1], #4
121 orr r3, r3, r7, push #24
122USER( strt r3, [r0], #4) @ May fault
123 mov ip, r0, lsl #32 - PAGE_SHIFT
124 rsb ip, ip, #0
125 movs ip, ip, lsr #32 - PAGE_SHIFT
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000126 beq .Lc2u_1fupi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 cmp r2, ip
128 movlt ip, r2
129 sub r2, r2, ip
130 subs ip, ip, #16
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000131 blt .Lc2u_1rem8lp
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000133.Lc2u_1cpy8lp: mov r3, r7, pull #8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134 ldmia r1!, {r4 - r7}
135 subs ip, ip, #16
136 orr r3, r3, r4, push #24
137 mov r4, r4, pull #8
138 orr r4, r4, r5, push #24
139 mov r5, r5, pull #8
140 orr r5, r5, r6, push #24
141 mov r6, r6, pull #8
142 orr r6, r6, r7, push #24
143 stmia r0!, {r3 - r6} @ Shouldnt fault
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000144 bpl .Lc2u_1cpy8lp
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000146.Lc2u_1rem8lp: tst ip, #8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 movne r3, r7, pull #8
148 ldmneia r1!, {r4, r7}
149 orrne r3, r3, r4, push #24
150 movne r4, r4, pull #8
151 orrne r4, r4, r7, push #24
152 stmneia r0!, {r3 - r4} @ Shouldnt fault
153 tst ip, #4
154 movne r3, r7, pull #8
155 ldrne r7, [r1], #4
156 orrne r3, r3, r7, push #24
157 strnet r3, [r0], #4 @ Shouldnt fault
158 ands ip, ip, #3
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000159 beq .Lc2u_1fupi
160.Lc2u_1nowords: mov r3, r7, get_byte_1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161 teq ip, #0
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000162 beq .Lc2u_finished
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163 cmp ip, #2
164USER( strbt r3, [r0], #1) @ May fault
165 movge r3, r7, get_byte_2
166USER( strgebt r3, [r0], #1) @ May fault
167 movgt r3, r7, get_byte_3
168USER( strgtbt r3, [r0], #1) @ May fault
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000169 b .Lc2u_finished
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000171.Lc2u_2fupi: subs r2, r2, #4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 addmi ip, r2, #4
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000173 bmi .Lc2u_2nowords
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 mov r3, r7, pull #16
175 ldr r7, [r1], #4
176 orr r3, r3, r7, push #16
177USER( strt r3, [r0], #4) @ May fault
178 mov ip, r0, lsl #32 - PAGE_SHIFT
179 rsb ip, ip, #0
180 movs ip, ip, lsr #32 - PAGE_SHIFT
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000181 beq .Lc2u_2fupi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 cmp r2, ip
183 movlt ip, r2
184 sub r2, r2, ip
185 subs ip, ip, #16
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000186 blt .Lc2u_2rem8lp
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000188.Lc2u_2cpy8lp: mov r3, r7, pull #16
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 ldmia r1!, {r4 - r7}
190 subs ip, ip, #16
191 orr r3, r3, r4, push #16
192 mov r4, r4, pull #16
193 orr r4, r4, r5, push #16
194 mov r5, r5, pull #16
195 orr r5, r5, r6, push #16
196 mov r6, r6, pull #16
197 orr r6, r6, r7, push #16
198 stmia r0!, {r3 - r6} @ Shouldnt fault
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000199 bpl .Lc2u_2cpy8lp
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000201.Lc2u_2rem8lp: tst ip, #8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202 movne r3, r7, pull #16
203 ldmneia r1!, {r4, r7}
204 orrne r3, r3, r4, push #16
205 movne r4, r4, pull #16
206 orrne r4, r4, r7, push #16
207 stmneia r0!, {r3 - r4} @ Shouldnt fault
208 tst ip, #4
209 movne r3, r7, pull #16
210 ldrne r7, [r1], #4
211 orrne r3, r3, r7, push #16
212 strnet r3, [r0], #4 @ Shouldnt fault
213 ands ip, ip, #3
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000214 beq .Lc2u_2fupi
215.Lc2u_2nowords: mov r3, r7, get_byte_2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 teq ip, #0
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000217 beq .Lc2u_finished
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 cmp ip, #2
219USER( strbt r3, [r0], #1) @ May fault
220 movge r3, r7, get_byte_3
221USER( strgebt r3, [r0], #1) @ May fault
222 ldrgtb r3, [r1], #0
223USER( strgtbt r3, [r0], #1) @ May fault
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000224 b .Lc2u_finished
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000226.Lc2u_3fupi: subs r2, r2, #4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 addmi ip, r2, #4
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000228 bmi .Lc2u_3nowords
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 mov r3, r7, pull #24
230 ldr r7, [r1], #4
231 orr r3, r3, r7, push #8
232USER( strt r3, [r0], #4) @ May fault
233 mov ip, r0, lsl #32 - PAGE_SHIFT
234 rsb ip, ip, #0
235 movs ip, ip, lsr #32 - PAGE_SHIFT
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000236 beq .Lc2u_3fupi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 cmp r2, ip
238 movlt ip, r2
239 sub r2, r2, ip
240 subs ip, ip, #16
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000241 blt .Lc2u_3rem8lp
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000243.Lc2u_3cpy8lp: mov r3, r7, pull #24
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 ldmia r1!, {r4 - r7}
245 subs ip, ip, #16
246 orr r3, r3, r4, push #8
247 mov r4, r4, pull #24
248 orr r4, r4, r5, push #8
249 mov r5, r5, pull #24
250 orr r5, r5, r6, push #8
251 mov r6, r6, pull #24
252 orr r6, r6, r7, push #8
253 stmia r0!, {r3 - r6} @ Shouldnt fault
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000254 bpl .Lc2u_3cpy8lp
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000256.Lc2u_3rem8lp: tst ip, #8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 movne r3, r7, pull #24
258 ldmneia r1!, {r4, r7}
259 orrne r3, r3, r4, push #8
260 movne r4, r4, pull #24
261 orrne r4, r4, r7, push #8
262 stmneia r0!, {r3 - r4} @ Shouldnt fault
263 tst ip, #4
264 movne r3, r7, pull #24
265 ldrne r7, [r1], #4
266 orrne r3, r3, r7, push #8
267 strnet r3, [r0], #4 @ Shouldnt fault
268 ands ip, ip, #3
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000269 beq .Lc2u_3fupi
270.Lc2u_3nowords: mov r3, r7, get_byte_3
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 teq ip, #0
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000272 beq .Lc2u_finished
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 cmp ip, #2
274USER( strbt r3, [r0], #1) @ May fault
275 ldrgeb r3, [r1], #1
276USER( strgebt r3, [r0], #1) @ May fault
277 ldrgtb r3, [r1], #0
278USER( strgtbt r3, [r0], #1) @ May fault
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000279 b .Lc2u_finished
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280
281 .section .fixup,"ax"
282 .align 0
Russell King1b93a712006-06-25 11:23:45 +01002839001: ldmfd sp!, {r0, r4 - r7, pc}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 .previous
285
Russell King02fcb972006-06-21 14:44:52 +0100286/* Prototype: unsigned long __copy_from_user(void *to,const void *from,unsigned long n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 * Purpose : copy a block from user memory to kernel memory
288 * Params : to - kernel memory
289 * : from - user memory
290 * : n - number of bytes to copy
291 * Returns : Number of bytes NOT copied.
292 */
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000293.Lcfu_dest_not_aligned:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 rsb ip, ip, #4
295 cmp ip, #2
296USER( ldrbt r3, [r1], #1) @ May fault
297 strb r3, [r0], #1
298USER( ldrgebt r3, [r1], #1) @ May fault
299 strgeb r3, [r0], #1
300USER( ldrgtbt r3, [r1], #1) @ May fault
301 strgtb r3, [r0], #1
302 sub r2, r2, ip
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000303 b .Lcfu_dest_aligned
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304
Russell King02fcb972006-06-21 14:44:52 +0100305ENTRY(__copy_from_user)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306 stmfd sp!, {r0, r2, r4 - r7, lr}
307 cmp r2, #4
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000308 blt .Lcfu_not_enough
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 ands ip, r0, #3
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000310 bne .Lcfu_dest_not_aligned
311.Lcfu_dest_aligned:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 ands ip, r1, #3
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000313 bne .Lcfu_src_not_aligned
314
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315/*
316 * Seeing as there has to be at least 8 bytes to copy, we can
317 * copy one word, and force a user-mode page fault...
318 */
319
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000320.Lcfu_0fupi: subs r2, r2, #4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 addmi ip, r2, #4
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000322 bmi .Lcfu_0nowords
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323USER( ldrt r3, [r1], #4)
324 str r3, [r0], #4
325 mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
326 rsb ip, ip, #0
327 movs ip, ip, lsr #32 - PAGE_SHIFT
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000328 beq .Lcfu_0fupi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329/*
330 * ip = max no. of bytes to copy before needing another "strt" insn
331 */
332 cmp r2, ip
333 movlt ip, r2
334 sub r2, r2, ip
335 subs ip, ip, #32
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000336 blt .Lcfu_0rem8lp
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000338.Lcfu_0cpy8lp: ldmia r1!, {r3 - r6} @ Shouldnt fault
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 stmia r0!, {r3 - r6}
340 ldmia r1!, {r3 - r6} @ Shouldnt fault
341 subs ip, ip, #32
342 stmia r0!, {r3 - r6}
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000343 bpl .Lcfu_0cpy8lp
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000345.Lcfu_0rem8lp: cmn ip, #16
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 ldmgeia r1!, {r3 - r6} @ Shouldnt fault
347 stmgeia r0!, {r3 - r6}
348 tst ip, #8
349 ldmneia r1!, {r3 - r4} @ Shouldnt fault
350 stmneia r0!, {r3 - r4}
351 tst ip, #4
352 ldrnet r3, [r1], #4 @ Shouldnt fault
353 strne r3, [r0], #4
354 ands ip, ip, #3
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000355 beq .Lcfu_0fupi
356.Lcfu_0nowords: teq ip, #0
357 beq .Lcfu_finished
358.Lcfu_nowords: cmp ip, #2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359USER( ldrbt r3, [r1], #1) @ May fault
360 strb r3, [r0], #1
361USER( ldrgebt r3, [r1], #1) @ May fault
362 strgeb r3, [r0], #1
363USER( ldrgtbt r3, [r1], #1) @ May fault
364 strgtb r3, [r0], #1
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000365 b .Lcfu_finished
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000367.Lcfu_not_enough:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 movs ip, r2
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000369 bne .Lcfu_nowords
370.Lcfu_finished: mov r0, #0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 add sp, sp, #8
Russell King1b93a712006-06-25 11:23:45 +0100372 ldmfd sp!, {r4 - r7, pc}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000374.Lcfu_src_not_aligned:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 bic r1, r1, #3
376USER( ldrt r7, [r1], #4) @ May fault
377 cmp ip, #2
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000378 bgt .Lcfu_3fupi
379 beq .Lcfu_2fupi
380.Lcfu_1fupi: subs r2, r2, #4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 addmi ip, r2, #4
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000382 bmi .Lcfu_1nowords
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 mov r3, r7, pull #8
384USER( ldrt r7, [r1], #4) @ May fault
385 orr r3, r3, r7, push #24
386 str r3, [r0], #4
387 mov ip, r1, lsl #32 - PAGE_SHIFT
388 rsb ip, ip, #0
389 movs ip, ip, lsr #32 - PAGE_SHIFT
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000390 beq .Lcfu_1fupi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 cmp r2, ip
392 movlt ip, r2
393 sub r2, r2, ip
394 subs ip, ip, #16
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000395 blt .Lcfu_1rem8lp
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000397.Lcfu_1cpy8lp: mov r3, r7, pull #8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 ldmia r1!, {r4 - r7} @ Shouldnt fault
399 subs ip, ip, #16
400 orr r3, r3, r4, push #24
401 mov r4, r4, pull #8
402 orr r4, r4, r5, push #24
403 mov r5, r5, pull #8
404 orr r5, r5, r6, push #24
405 mov r6, r6, pull #8
406 orr r6, r6, r7, push #24
407 stmia r0!, {r3 - r6}
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000408 bpl .Lcfu_1cpy8lp
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000410.Lcfu_1rem8lp: tst ip, #8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 movne r3, r7, pull #8
412 ldmneia r1!, {r4, r7} @ Shouldnt fault
413 orrne r3, r3, r4, push #24
414 movne r4, r4, pull #8
415 orrne r4, r4, r7, push #24
416 stmneia r0!, {r3 - r4}
417 tst ip, #4
418 movne r3, r7, pull #8
419USER( ldrnet r7, [r1], #4) @ May fault
420 orrne r3, r3, r7, push #24
421 strne r3, [r0], #4
422 ands ip, ip, #3
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000423 beq .Lcfu_1fupi
424.Lcfu_1nowords: mov r3, r7, get_byte_1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 teq ip, #0
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000426 beq .Lcfu_finished
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 cmp ip, #2
428 strb r3, [r0], #1
429 movge r3, r7, get_byte_2
430 strgeb r3, [r0], #1
431 movgt r3, r7, get_byte_3
432 strgtb r3, [r0], #1
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000433 b .Lcfu_finished
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000435.Lcfu_2fupi: subs r2, r2, #4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 addmi ip, r2, #4
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000437 bmi .Lcfu_2nowords
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 mov r3, r7, pull #16
439USER( ldrt r7, [r1], #4) @ May fault
440 orr r3, r3, r7, push #16
441 str r3, [r0], #4
442 mov ip, r1, lsl #32 - PAGE_SHIFT
443 rsb ip, ip, #0
444 movs ip, ip, lsr #32 - PAGE_SHIFT
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000445 beq .Lcfu_2fupi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 cmp r2, ip
447 movlt ip, r2
448 sub r2, r2, ip
449 subs ip, ip, #16
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000450 blt .Lcfu_2rem8lp
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000452
453.Lcfu_2cpy8lp: mov r3, r7, pull #16
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 ldmia r1!, {r4 - r7} @ Shouldnt fault
455 subs ip, ip, #16
456 orr r3, r3, r4, push #16
457 mov r4, r4, pull #16
458 orr r4, r4, r5, push #16
459 mov r5, r5, pull #16
460 orr r5, r5, r6, push #16
461 mov r6, r6, pull #16
462 orr r6, r6, r7, push #16
463 stmia r0!, {r3 - r6}
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000464 bpl .Lcfu_2cpy8lp
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000466.Lcfu_2rem8lp: tst ip, #8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 movne r3, r7, pull #16
468 ldmneia r1!, {r4, r7} @ Shouldnt fault
469 orrne r3, r3, r4, push #16
470 movne r4, r4, pull #16
471 orrne r4, r4, r7, push #16
472 stmneia r0!, {r3 - r4}
473 tst ip, #4
474 movne r3, r7, pull #16
475USER( ldrnet r7, [r1], #4) @ May fault
476 orrne r3, r3, r7, push #16
477 strne r3, [r0], #4
478 ands ip, ip, #3
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000479 beq .Lcfu_2fupi
480.Lcfu_2nowords: mov r3, r7, get_byte_2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 teq ip, #0
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000482 beq .Lcfu_finished
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 cmp ip, #2
484 strb r3, [r0], #1
485 movge r3, r7, get_byte_3
486 strgeb r3, [r0], #1
487USER( ldrgtbt r3, [r1], #0) @ May fault
488 strgtb r3, [r0], #1
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000489 b .Lcfu_finished
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000491.Lcfu_3fupi: subs r2, r2, #4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 addmi ip, r2, #4
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000493 bmi .Lcfu_3nowords
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 mov r3, r7, pull #24
495USER( ldrt r7, [r1], #4) @ May fault
496 orr r3, r3, r7, push #8
497 str r3, [r0], #4
498 mov ip, r1, lsl #32 - PAGE_SHIFT
499 rsb ip, ip, #0
500 movs ip, ip, lsr #32 - PAGE_SHIFT
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000501 beq .Lcfu_3fupi
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 cmp r2, ip
503 movlt ip, r2
504 sub r2, r2, ip
505 subs ip, ip, #16
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000506 blt .Lcfu_3rem8lp
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000508.Lcfu_3cpy8lp: mov r3, r7, pull #24
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 ldmia r1!, {r4 - r7} @ Shouldnt fault
510 orr r3, r3, r4, push #8
511 mov r4, r4, pull #24
512 orr r4, r4, r5, push #8
513 mov r5, r5, pull #24
514 orr r5, r5, r6, push #8
515 mov r6, r6, pull #24
516 orr r6, r6, r7, push #8
517 stmia r0!, {r3 - r6}
518 subs ip, ip, #16
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000519 bpl .Lcfu_3cpy8lp
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000521.Lcfu_3rem8lp: tst ip, #8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 movne r3, r7, pull #24
523 ldmneia r1!, {r4, r7} @ Shouldnt fault
524 orrne r3, r3, r4, push #8
525 movne r4, r4, pull #24
526 orrne r4, r4, r7, push #8
527 stmneia r0!, {r3 - r4}
528 tst ip, #4
529 movne r3, r7, pull #24
530USER( ldrnet r7, [r1], #4) @ May fault
531 orrne r3, r3, r7, push #8
532 strne r3, [r0], #4
533 ands ip, ip, #3
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000534 beq .Lcfu_3fupi
535.Lcfu_3nowords: mov r3, r7, get_byte_3
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 teq ip, #0
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000537 beq .Lcfu_finished
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 cmp ip, #2
539 strb r3, [r0], #1
540USER( ldrgebt r3, [r1], #1) @ May fault
541 strgeb r3, [r0], #1
542USER( ldrgtbt r3, [r1], #1) @ May fault
543 strgtb r3, [r0], #1
Nicolas Pitre7ba11a92005-11-11 21:51:47 +0000544 b .Lcfu_finished
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545
546 .section .fixup,"ax"
547 .align 0
548 /*
549 * We took an exception. r0 contains a pointer to
550 * the byte not copied.
551 */
5529001: ldr r2, [sp], #4 @ void *to
553 sub r2, r0, r2 @ bytes copied
554 ldr r1, [sp], #4 @ unsigned long count
555 subs r4, r1, r2 @ bytes left to copy
556 movne r1, r4
557 blne __memzero
558 mov r0, r4
Russell King1b93a712006-06-25 11:23:45 +0100559 ldmfd sp!, {r4 - r7, pc}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 .previous
561