Merge branch 'linus' into x86/core
[linux-2.6] / arch / sh / include / asm / uaccess_32.h
1 /*
2  * User space memory access functions
3  *
4  * Copyright (C) 1999, 2002  Niibe Yutaka
5  * Copyright (C) 2003 - 2008  Paul Mundt
6  *
7  *  Based on:
8  *     MIPS implementation version 1.15 by
9  *              Copyright (C) 1996, 1997, 1998 by Ralf Baechle
10  *     and i386 version.
11  */
12 #ifndef __ASM_SH_UACCESS_32_H
13 #define __ASM_SH_UACCESS_32_H
14
15 #define __get_user_size(x,ptr,size,retval)                      \
16 do {                                                            \
17         retval = 0;                                             \
18         switch (size) {                                         \
19         case 1:                                                 \
20                 __get_user_asm(x, ptr, retval, "b");            \
21                 break;                                          \
22         case 2:                                                 \
23                 __get_user_asm(x, ptr, retval, "w");            \
24                 break;                                          \
25         case 4:                                                 \
26                 __get_user_asm(x, ptr, retval, "l");            \
27                 break;                                          \
28         default:                                                \
29                 __get_user_unknown();                           \
30                 break;                                          \
31         }                                                       \
32 } while (0)
33
34 #ifdef CONFIG_MMU
35 #define __get_user_asm(x, addr, err, insn) \
36 ({ \
37 __asm__ __volatile__( \
38         "1:\n\t" \
39         "mov." insn "   %2, %1\n\t" \
40         "2:\n" \
41         ".section       .fixup,\"ax\"\n" \
42         "3:\n\t" \
43         "mov    #0, %1\n\t" \
44         "mov.l  4f, %0\n\t" \
45         "jmp    @%0\n\t" \
46         " mov   %3, %0\n\t" \
47         ".balign        4\n" \
48         "4:     .long   2b\n\t" \
49         ".previous\n" \
50         ".section       __ex_table,\"a\"\n\t" \
51         ".long  1b, 3b\n\t" \
52         ".previous" \
53         :"=&r" (err), "=&r" (x) \
54         :"m" (__m(addr)), "i" (-EFAULT), "0" (err)); })
55 #else
56 #define __get_user_asm(x, addr, err, insn)              \
57 do {                                                    \
58         __asm__ __volatile__ (                          \
59                 "mov." insn "   %1, %0\n\t"             \
60                 : "=&r" (x)                             \
61                 : "m" (__m(addr))                       \
62         );                                              \
63 } while (0)
64 #endif /* CONFIG_MMU */
65
66 extern void __get_user_unknown(void);
67
68 #define __put_user_size(x,ptr,size,retval)              \
69 do {                                                    \
70         retval = 0;                                     \
71         switch (size) {                                 \
72         case 1:                                         \
73                 __put_user_asm(x, ptr, retval, "b");    \
74                 break;                                  \
75         case 2:                                         \
76                 __put_user_asm(x, ptr, retval, "w");    \
77                 break;                                  \
78         case 4:                                         \
79                 __put_user_asm(x, ptr, retval, "l");    \
80                 break;                                  \
81         case 8:                                         \
82                 __put_user_u64(x, ptr, retval);         \
83                 break;                                  \
84         default:                                        \
85                 __put_user_unknown();                   \
86         }                                               \
87 } while (0)
88
89 #ifdef CONFIG_MMU
90 #define __put_user_asm(x, addr, err, insn)                      \
91 do {                                                            \
92         __asm__ __volatile__ (                                  \
93                 "1:\n\t"                                        \
94                 "mov." insn "   %1, %2\n\t"                     \
95                 "2:\n"                                          \
96                 ".section       .fixup,\"ax\"\n"                \
97                 "3:\n\t"                                        \
98                 "mov.l  4f, %0\n\t"                             \
99                 "jmp    @%0\n\t"                                \
100                 " mov   %3, %0\n\t"                             \
101                 ".balign        4\n"                            \
102                 "4:     .long   2b\n\t"                         \
103                 ".previous\n"                                   \
104                 ".section       __ex_table,\"a\"\n\t"           \
105                 ".long  1b, 3b\n\t"                             \
106                 ".previous"                                     \
107                 : "=&r" (err)                                   \
108                 : "r" (x), "m" (__m(addr)), "i" (-EFAULT),      \
109                   "0" (err)                                     \
110                 : "memory"                                      \
111         );                                                      \
112 } while (0)
113 #else
114 #define __put_user_asm(x, addr, err, insn)              \
115 do {                                                    \
116         __asm__ __volatile__ (                          \
117                 "mov." insn "   %0, %1\n\t"             \
118                 : /* no outputs */                      \
119                 : "r" (x), "m" (__m(addr))              \
120                 : "memory"                              \
121         );                                              \
122 } while (0)
123 #endif /* CONFIG_MMU */
124
125 #if defined(CONFIG_CPU_LITTLE_ENDIAN)
126 #define __put_user_u64(val,addr,retval) \
127 ({ \
128 __asm__ __volatile__( \
129         "1:\n\t" \
130         "mov.l  %R1,%2\n\t" \
131         "mov.l  %S1,%T2\n\t" \
132         "2:\n" \
133         ".section       .fixup,\"ax\"\n" \
134         "3:\n\t" \
135         "mov.l  4f,%0\n\t" \
136         "jmp    @%0\n\t" \
137         " mov   %3,%0\n\t" \
138         ".balign        4\n" \
139         "4:     .long   2b\n\t" \
140         ".previous\n" \
141         ".section       __ex_table,\"a\"\n\t" \
142         ".long  1b, 3b\n\t" \
143         ".previous" \
144         : "=r" (retval) \
145         : "r" (val), "m" (__m(addr)), "i" (-EFAULT), "0" (retval) \
146         : "memory"); })
147 #else
148 #define __put_user_u64(val,addr,retval) \
149 ({ \
150 __asm__ __volatile__( \
151         "1:\n\t" \
152         "mov.l  %S1,%2\n\t" \
153         "mov.l  %R1,%T2\n\t" \
154         "2:\n" \
155         ".section       .fixup,\"ax\"\n" \
156         "3:\n\t" \
157         "mov.l  4f,%0\n\t" \
158         "jmp    @%0\n\t" \
159         " mov   %3,%0\n\t" \
160         ".balign        4\n" \
161         "4:     .long   2b\n\t" \
162         ".previous\n" \
163         ".section       __ex_table,\"a\"\n\t" \
164         ".long  1b, 3b\n\t" \
165         ".previous" \
166         : "=r" (retval) \
167         : "r" (val), "m" (__m(addr)), "i" (-EFAULT), "0" (retval) \
168         : "memory"); })
169 #endif
170
171 extern void __put_user_unknown(void);
172
173 static inline int
174 __strncpy_from_user(unsigned long __dest, unsigned long __user __src, int __count)
175 {
176         __kernel_size_t res;
177         unsigned long __dummy, _d, _s, _c;
178
179         __asm__ __volatile__(
180                 "9:\n"
181                 "mov.b  @%2+, %1\n\t"
182                 "cmp/eq #0, %1\n\t"
183                 "bt/s   2f\n"
184                 "1:\n"
185                 "mov.b  %1, @%3\n\t"
186                 "dt     %4\n\t"
187                 "bf/s   9b\n\t"
188                 " add   #1, %3\n\t"
189                 "2:\n\t"
190                 "sub    %4, %0\n"
191                 "3:\n"
192                 ".section .fixup,\"ax\"\n"
193                 "4:\n\t"
194                 "mov.l  5f, %1\n\t"
195                 "jmp    @%1\n\t"
196                 " mov   %9, %0\n\t"
197                 ".balign 4\n"
198                 "5:     .long 3b\n"
199                 ".previous\n"
200                 ".section __ex_table,\"a\"\n"
201                 "       .balign 4\n"
202                 "       .long 9b,4b\n"
203                 ".previous"
204                 : "=r" (res), "=&z" (__dummy), "=r" (_s), "=r" (_d), "=r"(_c)
205                 : "0" (__count), "2" (__src), "3" (__dest), "4" (__count),
206                   "i" (-EFAULT)
207                 : "memory", "t");
208
209         return res;
210 }
211
212 /*
213  * Return the size of a string (including the ending 0 even when we have
214  * exceeded the maximum string length).
215  */
216 static inline long __strnlen_user(const char __user *__s, long __n)
217 {
218         unsigned long res;
219         unsigned long __dummy;
220
221         __asm__ __volatile__(
222                 "1:\t"
223                 "mov.b  @(%0,%3), %1\n\t"
224                 "cmp/eq %4, %0\n\t"
225                 "bt/s   2f\n\t"
226                 " add   #1, %0\n\t"
227                 "tst    %1, %1\n\t"
228                 "bf     1b\n\t"
229                 "2:\n"
230                 ".section .fixup,\"ax\"\n"
231                 "3:\n\t"
232                 "mov.l  4f, %1\n\t"
233                 "jmp    @%1\n\t"
234                 " mov   #0, %0\n"
235                 ".balign 4\n"
236                 "4:     .long 2b\n"
237                 ".previous\n"
238                 ".section __ex_table,\"a\"\n"
239                 "       .balign 4\n"
240                 "       .long 1b,3b\n"
241                 ".previous"
242                 : "=z" (res), "=&r" (__dummy)
243                 : "0" (0), "r" (__s), "r" (__n)
244                 : "t");
245         return res;
246 }
247
248 #endif /* __ASM_SH_UACCESS_32_H */