2 * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
3 * Copyright (C) 2009 PetaLogix
4 * Copyright (C) 2007 LynuxWorks, Inc.
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
11 #include <linux/errno.h>
12 #include <linux/linkage.h>
16 * int __strncpy_user(char *to, char *from, int len);
19 * -EFAULT for an exception
20 * len if we hit the buffer limit
25 .globl __strncpy_user;
26 .type __strncpy_user, @function
38 addik r3,r7,0 /* temp_count = len */
44 beqi r3,2f /* break on len */
48 addik r6,r6,1 /* delay slot */
49 addik r3,r3,1 /* undo "temp_count--" */
51 rsubk r3,r3,r7 /* temp_count = len - temp_count */
55 .size __strncpy_user, . - __strncpy_user
63 .section __ex_table, "a"
67 * int __strnlen_user(char __user *str, int maxlen);
71 * maxlen + 1 if no NUL byte found within maxlen bytes
72 * size of the string (including NUL byte)
76 .globl __strnlen_user;
77 .type __strnlen_user, @function
84 beqid r4,2f /* break on NUL */
85 addik r3,r3,-1 /* delay slot */
88 addik r5,r5,1 /* delay slot */
90 addik r3,r3,-1 /* for break on len */
96 .size __strnlen_user, . - __strnlen_user
103 .section __ex_table,"a"
106 /* Loop unrolling for __copy_tofrom_user */
107 #define COPY(offset) \
108 1: lwi r4 , r6, 0x0000 + offset; \
109 2: lwi r19, r6, 0x0004 + offset; \
110 3: lwi r20, r6, 0x0008 + offset; \
111 4: lwi r21, r6, 0x000C + offset; \
112 5: lwi r22, r6, 0x0010 + offset; \
113 6: lwi r23, r6, 0x0014 + offset; \
114 7: lwi r24, r6, 0x0018 + offset; \
115 8: lwi r25, r6, 0x001C + offset; \
116 9: swi r4 , r5, 0x0000 + offset; \
117 10: swi r19, r5, 0x0004 + offset; \
118 11: swi r20, r5, 0x0008 + offset; \
119 12: swi r21, r5, 0x000C + offset; \
120 13: swi r22, r5, 0x0010 + offset; \
121 14: swi r23, r5, 0x0014 + offset; \
122 15: swi r24, r5, 0x0018 + offset; \
123 16: swi r25, r5, 0x001C + offset; \
124 .section __ex_table,"a"; \
143 #define COPY_80(offset) \
144 COPY(0x00 + offset);\
145 COPY(0x20 + offset);\
146 COPY(0x40 + offset);\
150 * int __copy_tofrom_user(char *to, char *from, int len)
153 * number of not copied bytes on error
156 .globl __copy_tofrom_user;
157 .type __copy_tofrom_user, @function
166 beqid r7, 0f /* zero size is not likely */
167 or r3, r5, r6 /* find if is any to/from unaligned */
168 or r3, r3, r7 /* find if count is unaligned */
169 andi r3, r3, 0x3 /* mask last 3 bits */
170 bneid r3, bu1 /* if r3 is not zero then byte copying */
173 rsubi r3, r7, PAGE_SIZE /* detect PAGE_SIZE */
177 w1: lw r4, r6, r3 /* at least one 4 byte copy */
186 .section __ex_table,"a"
191 .align 4 /* Alignment is important to keep icache happy */
192 page: /* Create room on stack and save registers for storign values */
201 loop: /* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */
202 /* Loop unrolling to get performance boost */
212 /* Restore register content */
226 .align 4 /* Alignment is important to keep icache happy */
231 addik r3,r3,1 /* delay slot */
236 .size __copy_tofrom_user, . - __copy_tofrom_user
238 .section __ex_table,"a"