Merge branches 'clk-mvebu', 'clk-const', 'clk-imx' and 'clk-rockchip' into clk-next
[linux-2.6-microblaze.git] / arch / mips / include / asm / unaligned-emul.h
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 #ifndef _ASM_MIPS_UNALIGNED_EMUL_H
3 #define _ASM_MIPS_UNALIGNED_EMUL_H
4
5 #include <asm/asm.h>
6
7 #ifdef __BIG_ENDIAN
8 #define  _LoadHW(addr, value, res, type)  \
9 do {                                                \
10         __asm__ __volatile__ (".set\tnoat\n"        \
11                 "1:\t"type##_lb("%0", "0(%2)")"\n"  \
12                 "2:\t"type##_lbu("$1", "1(%2)")"\n\t"\
13                 "sll\t%0, 0x8\n\t"                  \
14                 "or\t%0, $1\n\t"                    \
15                 "li\t%1, 0\n"                       \
16                 "3:\t.set\tat\n\t"                  \
17                 ".insn\n\t"                         \
18                 ".section\t.fixup,\"ax\"\n\t"       \
19                 "4:\tli\t%1, %3\n\t"                \
20                 "j\t3b\n\t"                         \
21                 ".previous\n\t"                     \
22                 ".section\t__ex_table,\"a\"\n\t"    \
23                 STR(PTR_WD)"\t1b, 4b\n\t"           \
24                 STR(PTR_WD)"\t2b, 4b\n\t"           \
25                 ".previous"                         \
26                 : "=&r" (value), "=r" (res)         \
27                 : "r" (addr), "i" (-EFAULT));       \
28 } while (0)
29
30 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR
31 #define  _LoadW(addr, value, res, type)   \
32 do {                                                \
33         __asm__ __volatile__ (                      \
34                 "1:\t"type##_lwl("%0", "(%2)")"\n"   \
35                 "2:\t"type##_lwr("%0", "3(%2)")"\n\t"\
36                 "li\t%1, 0\n"                       \
37                 "3:\n\t"                            \
38                 ".insn\n\t"                         \
39                 ".section\t.fixup,\"ax\"\n\t"       \
40                 "4:\tli\t%1, %3\n\t"                \
41                 "j\t3b\n\t"                         \
42                 ".previous\n\t"                     \
43                 ".section\t__ex_table,\"a\"\n\t"    \
44                 STR(PTR_WD)"\t1b, 4b\n\t"           \
45                 STR(PTR_WD)"\t2b, 4b\n\t"           \
46                 ".previous"                         \
47                 : "=&r" (value), "=r" (res)         \
48                 : "r" (addr), "i" (-EFAULT));       \
49 } while (0)
50
51 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */
52 /* For CPUs without lwl instruction */
53 #define  _LoadW(addr, value, res, type) \
54 do {                                                \
55         __asm__ __volatile__ (                      \
56                 ".set\tpush\n"                      \
57                 ".set\tnoat\n\t"                    \
58                 "1:"type##_lb("%0", "0(%2)")"\n\t"  \
59                 "2:"type##_lbu("$1", "1(%2)")"\n\t" \
60                 "sll\t%0, 0x8\n\t"                  \
61                 "or\t%0, $1\n\t"                    \
62                 "3:"type##_lbu("$1", "2(%2)")"\n\t" \
63                 "sll\t%0, 0x8\n\t"                  \
64                 "or\t%0, $1\n\t"                    \
65                 "4:"type##_lbu("$1", "3(%2)")"\n\t" \
66                 "sll\t%0, 0x8\n\t"                  \
67                 "or\t%0, $1\n\t"                    \
68                 "li\t%1, 0\n"                       \
69                 ".set\tpop\n"                       \
70                 "10:\n\t"                           \
71                 ".insn\n\t"                         \
72                 ".section\t.fixup,\"ax\"\n\t"       \
73                 "11:\tli\t%1, %3\n\t"               \
74                 "j\t10b\n\t"                        \
75                 ".previous\n\t"                     \
76                 ".section\t__ex_table,\"a\"\n\t"    \
77                 STR(PTR_WD)"\t1b, 11b\n\t"          \
78                 STR(PTR_WD)"\t2b, 11b\n\t"          \
79                 STR(PTR_WD)"\t3b, 11b\n\t"          \
80                 STR(PTR_WD)"\t4b, 11b\n\t"          \
81                 ".previous"                         \
82                 : "=&r" (value), "=r" (res)         \
83                 : "r" (addr), "i" (-EFAULT));       \
84 } while (0)
85
86 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
87
88 #define  _LoadHWU(addr, value, res, type) \
89 do {                                                \
90         __asm__ __volatile__ (                      \
91                 ".set\tnoat\n"                      \
92                 "1:\t"type##_lbu("%0", "0(%2)")"\n" \
93                 "2:\t"type##_lbu("$1", "1(%2)")"\n\t"\
94                 "sll\t%0, 0x8\n\t"                  \
95                 "or\t%0, $1\n\t"                    \
96                 "li\t%1, 0\n"                       \
97                 "3:\n\t"                            \
98                 ".insn\n\t"                         \
99                 ".set\tat\n\t"                      \
100                 ".section\t.fixup,\"ax\"\n\t"       \
101                 "4:\tli\t%1, %3\n\t"                \
102                 "j\t3b\n\t"                         \
103                 ".previous\n\t"                     \
104                 ".section\t__ex_table,\"a\"\n\t"    \
105                 STR(PTR_WD)"\t1b, 4b\n\t"           \
106                 STR(PTR_WD)"\t2b, 4b\n\t"           \
107                 ".previous"                         \
108                 : "=&r" (value), "=r" (res)         \
109                 : "r" (addr), "i" (-EFAULT));       \
110 } while (0)
111
112 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR
113 #define  _LoadWU(addr, value, res, type)  \
114 do {                                                \
115         __asm__ __volatile__ (                      \
116                 "1:\t"type##_lwl("%0", "(%2)")"\n"  \
117                 "2:\t"type##_lwr("%0", "3(%2)")"\n\t"\
118                 "dsll\t%0, %0, 32\n\t"              \
119                 "dsrl\t%0, %0, 32\n\t"              \
120                 "li\t%1, 0\n"                       \
121                 "3:\n\t"                            \
122                 ".insn\n\t"                         \
123                 "\t.section\t.fixup,\"ax\"\n\t"     \
124                 "4:\tli\t%1, %3\n\t"                \
125                 "j\t3b\n\t"                         \
126                 ".previous\n\t"                     \
127                 ".section\t__ex_table,\"a\"\n\t"    \
128                 STR(PTR_WD)"\t1b, 4b\n\t"           \
129                 STR(PTR_WD)"\t2b, 4b\n\t"           \
130                 ".previous"                         \
131                 : "=&r" (value), "=r" (res)         \
132                 : "r" (addr), "i" (-EFAULT));       \
133 } while (0)
134
135 #define  _LoadDW(addr, value, res)  \
136 do {                                                \
137         __asm__ __volatile__ (                      \
138                 "1:\tldl\t%0, (%2)\n"               \
139                 "2:\tldr\t%0, 7(%2)\n\t"            \
140                 "li\t%1, 0\n"                       \
141                 "3:\n\t"                            \
142                 ".insn\n\t"                         \
143                 "\t.section\t.fixup,\"ax\"\n\t"     \
144                 "4:\tli\t%1, %3\n\t"                \
145                 "j\t3b\n\t"                         \
146                 ".previous\n\t"                     \
147                 ".section\t__ex_table,\"a\"\n\t"    \
148                 STR(PTR_WD)"\t1b, 4b\n\t"           \
149                 STR(PTR_WD)"\t2b, 4b\n\t"           \
150                 ".previous"                         \
151                 : "=&r" (value), "=r" (res)         \
152                 : "r" (addr), "i" (-EFAULT));       \
153 } while (0)
154
155 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */
156 /* For CPUs without lwl and ldl instructions */
157 #define  _LoadWU(addr, value, res, type) \
158 do {                                                \
159         __asm__ __volatile__ (                      \
160                 ".set\tpush\n\t"                    \
161                 ".set\tnoat\n\t"                    \
162                 "1:"type##_lbu("%0", "0(%2)")"\n\t" \
163                 "2:"type##_lbu("$1", "1(%2)")"\n\t" \
164                 "sll\t%0, 0x8\n\t"                  \
165                 "or\t%0, $1\n\t"                    \
166                 "3:"type##_lbu("$1", "2(%2)")"\n\t" \
167                 "sll\t%0, 0x8\n\t"                  \
168                 "or\t%0, $1\n\t"                    \
169                 "4:"type##_lbu("$1", "3(%2)")"\n\t" \
170                 "sll\t%0, 0x8\n\t"                  \
171                 "or\t%0, $1\n\t"                    \
172                 "li\t%1, 0\n"                       \
173                 ".set\tpop\n"                       \
174                 "10:\n\t"                           \
175                 ".insn\n\t"                         \
176                 ".section\t.fixup,\"ax\"\n\t"       \
177                 "11:\tli\t%1, %3\n\t"               \
178                 "j\t10b\n\t"                        \
179                 ".previous\n\t"                     \
180                 ".section\t__ex_table,\"a\"\n\t"    \
181                 STR(PTR_WD)"\t1b, 11b\n\t"          \
182                 STR(PTR_WD)"\t2b, 11b\n\t"          \
183                 STR(PTR_WD)"\t3b, 11b\n\t"          \
184                 STR(PTR_WD)"\t4b, 11b\n\t"          \
185                 ".previous"                         \
186                 : "=&r" (value), "=r" (res)         \
187                 : "r" (addr), "i" (-EFAULT));       \
188 } while (0)
189
190 #define  _LoadDW(addr, value, res)  \
191 do {                                                \
192         __asm__ __volatile__ (                      \
193                 ".set\tpush\n\t"                    \
194                 ".set\tnoat\n\t"                    \
195                 "1:lb\t%0, 0(%2)\n\t"               \
196                 "2:lbu\t $1, 1(%2)\n\t"             \
197                 "dsll\t%0, 0x8\n\t"                 \
198                 "or\t%0, $1\n\t"                    \
199                 "3:lbu\t$1, 2(%2)\n\t"              \
200                 "dsll\t%0, 0x8\n\t"                 \
201                 "or\t%0, $1\n\t"                    \
202                 "4:lbu\t$1, 3(%2)\n\t"              \
203                 "dsll\t%0, 0x8\n\t"                 \
204                 "or\t%0, $1\n\t"                    \
205                 "5:lbu\t$1, 4(%2)\n\t"              \
206                 "dsll\t%0, 0x8\n\t"                 \
207                 "or\t%0, $1\n\t"                    \
208                 "6:lbu\t$1, 5(%2)\n\t"              \
209                 "dsll\t%0, 0x8\n\t"                 \
210                 "or\t%0, $1\n\t"                    \
211                 "7:lbu\t$1, 6(%2)\n\t"              \
212                 "dsll\t%0, 0x8\n\t"                 \
213                 "or\t%0, $1\n\t"                    \
214                 "8:lbu\t$1, 7(%2)\n\t"              \
215                 "dsll\t%0, 0x8\n\t"                 \
216                 "or\t%0, $1\n\t"                    \
217                 "li\t%1, 0\n"                       \
218                 ".set\tpop\n\t"                     \
219                 "10:\n\t"                           \
220                 ".insn\n\t"                         \
221                 ".section\t.fixup,\"ax\"\n\t"       \
222                 "11:\tli\t%1, %3\n\t"               \
223                 "j\t10b\n\t"                        \
224                 ".previous\n\t"                     \
225                 ".section\t__ex_table,\"a\"\n\t"    \
226                 STR(PTR_WD)"\t1b, 11b\n\t"          \
227                 STR(PTR_WD)"\t2b, 11b\n\t"          \
228                 STR(PTR_WD)"\t3b, 11b\n\t"          \
229                 STR(PTR_WD)"\t4b, 11b\n\t"          \
230                 STR(PTR_WD)"\t5b, 11b\n\t"          \
231                 STR(PTR_WD)"\t6b, 11b\n\t"          \
232                 STR(PTR_WD)"\t7b, 11b\n\t"          \
233                 STR(PTR_WD)"\t8b, 11b\n\t"          \
234                 ".previous"                         \
235                 : "=&r" (value), "=r" (res)         \
236                 : "r" (addr), "i" (-EFAULT));       \
237 } while (0)
238
239 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
240
241
242 #define  _StoreHW(addr, value, res, type) \
243 do {                                                \
244         __asm__ __volatile__ (                      \
245                 ".set\tnoat\n"                      \
246                 "1:\t"type##_sb("%1", "1(%2)")"\n"  \
247                 "srl\t$1, %1, 0x8\n"                \
248                 "2:\t"type##_sb("$1", "0(%2)")"\n"  \
249                 ".set\tat\n\t"                      \
250                 "li\t%0, 0\n"                       \
251                 "3:\n\t"                            \
252                 ".insn\n\t"                         \
253                 ".section\t.fixup,\"ax\"\n\t"       \
254                 "4:\tli\t%0, %3\n\t"                \
255                 "j\t3b\n\t"                         \
256                 ".previous\n\t"                     \
257                 ".section\t__ex_table,\"a\"\n\t"    \
258                 STR(PTR_WD)"\t1b, 4b\n\t"           \
259                 STR(PTR_WD)"\t2b, 4b\n\t"           \
260                 ".previous"                         \
261                 : "=r" (res)                        \
262                 : "r" (value), "r" (addr), "i" (-EFAULT));\
263 } while (0)
264
265 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR
266 #define  _StoreW(addr, value, res, type)  \
267 do {                                                \
268         __asm__ __volatile__ (                      \
269                 "1:\t"type##_swl("%1", "(%2)")"\n"  \
270                 "2:\t"type##_swr("%1", "3(%2)")"\n\t"\
271                 "li\t%0, 0\n"                       \
272                 "3:\n\t"                            \
273                 ".insn\n\t"                         \
274                 ".section\t.fixup,\"ax\"\n\t"       \
275                 "4:\tli\t%0, %3\n\t"                \
276                 "j\t3b\n\t"                         \
277                 ".previous\n\t"                     \
278                 ".section\t__ex_table,\"a\"\n\t"    \
279                 STR(PTR_WD)"\t1b, 4b\n\t"           \
280                 STR(PTR_WD)"\t2b, 4b\n\t"           \
281                 ".previous"                         \
282                 : "=r" (res)                                \
283                 : "r" (value), "r" (addr), "i" (-EFAULT));  \
284 } while (0)
285
286 #define  _StoreDW(addr, value, res) \
287 do {                                                \
288         __asm__ __volatile__ (                      \
289                 "1:\tsdl\t%1,(%2)\n"                \
290                 "2:\tsdr\t%1, 7(%2)\n\t"            \
291                 "li\t%0, 0\n"                       \
292                 "3:\n\t"                            \
293                 ".insn\n\t"                         \
294                 ".section\t.fixup,\"ax\"\n\t"       \
295                 "4:\tli\t%0, %3\n\t"                \
296                 "j\t3b\n\t"                         \
297                 ".previous\n\t"                     \
298                 ".section\t__ex_table,\"a\"\n\t"    \
299                 STR(PTR_WD)"\t1b, 4b\n\t"           \
300                 STR(PTR_WD)"\t2b, 4b\n\t"           \
301                 ".previous"                         \
302                 : "=r" (res)                                \
303                 : "r" (value), "r" (addr), "i" (-EFAULT));  \
304 } while (0)
305
306 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */
307 #define  _StoreW(addr, value, res, type)  \
308 do {                                                \
309         __asm__ __volatile__ (                      \
310                 ".set\tpush\n\t"                    \
311                 ".set\tnoat\n\t"                    \
312                 "1:"type##_sb("%1", "3(%2)")"\n\t"  \
313                 "srl\t$1, %1, 0x8\n\t"              \
314                 "2:"type##_sb("$1", "2(%2)")"\n\t"  \
315                 "srl\t$1, $1,  0x8\n\t"             \
316                 "3:"type##_sb("$1", "1(%2)")"\n\t"  \
317                 "srl\t$1, $1, 0x8\n\t"              \
318                 "4:"type##_sb("$1", "0(%2)")"\n\t"  \
319                 ".set\tpop\n\t"                     \
320                 "li\t%0, 0\n"                       \
321                 "10:\n\t"                           \
322                 ".insn\n\t"                         \
323                 ".section\t.fixup,\"ax\"\n\t"       \
324                 "11:\tli\t%0, %3\n\t"               \
325                 "j\t10b\n\t"                        \
326                 ".previous\n\t"                     \
327                 ".section\t__ex_table,\"a\"\n\t"    \
328                 STR(PTR_WD)"\t1b, 11b\n\t"          \
329                 STR(PTR_WD)"\t2b, 11b\n\t"          \
330                 STR(PTR_WD)"\t3b, 11b\n\t"          \
331                 STR(PTR_WD)"\t4b, 11b\n\t"          \
332                 ".previous"                         \
333                 : "=&r" (res)                               \
334                 : "r" (value), "r" (addr), "i" (-EFAULT)    \
335                 : "memory");                                \
336 } while (0)
337
338 #define  _StoreDW(addr, value, res) \
339 do {                                                \
340         __asm__ __volatile__ (                      \
341                 ".set\tpush\n\t"                    \
342                 ".set\tnoat\n\t"                    \
343                 "1:sb\t%1, 7(%2)\n\t"               \
344                 "dsrl\t$1, %1, 0x8\n\t"             \
345                 "2:sb\t$1, 6(%2)\n\t"               \
346                 "dsrl\t$1, $1, 0x8\n\t"             \
347                 "3:sb\t$1, 5(%2)\n\t"               \
348                 "dsrl\t$1, $1, 0x8\n\t"             \
349                 "4:sb\t$1, 4(%2)\n\t"               \
350                 "dsrl\t$1, $1, 0x8\n\t"             \
351                 "5:sb\t$1, 3(%2)\n\t"               \
352                 "dsrl\t$1, $1, 0x8\n\t"             \
353                 "6:sb\t$1, 2(%2)\n\t"               \
354                 "dsrl\t$1, $1, 0x8\n\t"             \
355                 "7:sb\t$1, 1(%2)\n\t"               \
356                 "dsrl\t$1, $1, 0x8\n\t"             \
357                 "8:sb\t$1, 0(%2)\n\t"               \
358                 "dsrl\t$1, $1, 0x8\n\t"             \
359                 ".set\tpop\n\t"                     \
360                 "li\t%0, 0\n"                       \
361                 "10:\n\t"                           \
362                 ".insn\n\t"                         \
363                 ".section\t.fixup,\"ax\"\n\t"       \
364                 "11:\tli\t%0, %3\n\t"               \
365                 "j\t10b\n\t"                        \
366                 ".previous\n\t"                     \
367                 ".section\t__ex_table,\"a\"\n\t"    \
368                 STR(PTR_WD)"\t1b, 11b\n\t"          \
369                 STR(PTR_WD)"\t2b, 11b\n\t"          \
370                 STR(PTR_WD)"\t3b, 11b\n\t"          \
371                 STR(PTR_WD)"\t4b, 11b\n\t"          \
372                 STR(PTR_WD)"\t5b, 11b\n\t"          \
373                 STR(PTR_WD)"\t6b, 11b\n\t"          \
374                 STR(PTR_WD)"\t7b, 11b\n\t"          \
375                 STR(PTR_WD)"\t8b, 11b\n\t"          \
376                 ".previous"                         \
377                 : "=&r" (res)                               \
378                 : "r" (value), "r" (addr), "i" (-EFAULT)    \
379                 : "memory");                                \
380 } while (0)
381
382 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
383
384 #else /* __BIG_ENDIAN */
385
386 #define  _LoadHW(addr, value, res, type)  \
387 do {                                                \
388         __asm__ __volatile__ (".set\tnoat\n"        \
389                 "1:\t"type##_lb("%0", "1(%2)")"\n"  \
390                 "2:\t"type##_lbu("$1", "0(%2)")"\n\t"\
391                 "sll\t%0, 0x8\n\t"                  \
392                 "or\t%0, $1\n\t"                    \
393                 "li\t%1, 0\n"                       \
394                 "3:\t.set\tat\n\t"                  \
395                 ".insn\n\t"                         \
396                 ".section\t.fixup,\"ax\"\n\t"       \
397                 "4:\tli\t%1, %3\n\t"                \
398                 "j\t3b\n\t"                         \
399                 ".previous\n\t"                     \
400                 ".section\t__ex_table,\"a\"\n\t"    \
401                 STR(PTR_WD)"\t1b, 4b\n\t"           \
402                 STR(PTR_WD)"\t2b, 4b\n\t"           \
403                 ".previous"                         \
404                 : "=&r" (value), "=r" (res)         \
405                 : "r" (addr), "i" (-EFAULT));       \
406 } while (0)
407
408 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR
409 #define  _LoadW(addr, value, res, type)   \
410 do {                                                \
411         __asm__ __volatile__ (                      \
412                 "1:\t"type##_lwl("%0", "3(%2)")"\n" \
413                 "2:\t"type##_lwr("%0", "(%2)")"\n\t"\
414                 "li\t%1, 0\n"                       \
415                 "3:\n\t"                            \
416                 ".insn\n\t"                         \
417                 ".section\t.fixup,\"ax\"\n\t"       \
418                 "4:\tli\t%1, %3\n\t"                \
419                 "j\t3b\n\t"                         \
420                 ".previous\n\t"                     \
421                 ".section\t__ex_table,\"a\"\n\t"    \
422                 STR(PTR_WD)"\t1b, 4b\n\t"           \
423                 STR(PTR_WD)"\t2b, 4b\n\t"           \
424                 ".previous"                         \
425                 : "=&r" (value), "=r" (res)         \
426                 : "r" (addr), "i" (-EFAULT));       \
427 } while (0)
428
429 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */
430 /* For CPUs without lwl instruction */
431 #define  _LoadW(addr, value, res, type) \
432 do {                                                \
433         __asm__ __volatile__ (                      \
434                 ".set\tpush\n"                      \
435                 ".set\tnoat\n\t"                    \
436                 "1:"type##_lb("%0", "3(%2)")"\n\t"  \
437                 "2:"type##_lbu("$1", "2(%2)")"\n\t" \
438                 "sll\t%0, 0x8\n\t"                  \
439                 "or\t%0, $1\n\t"                    \
440                 "3:"type##_lbu("$1", "1(%2)")"\n\t" \
441                 "sll\t%0, 0x8\n\t"                  \
442                 "or\t%0, $1\n\t"                    \
443                 "4:"type##_lbu("$1", "0(%2)")"\n\t" \
444                 "sll\t%0, 0x8\n\t"                  \
445                 "or\t%0, $1\n\t"                    \
446                 "li\t%1, 0\n"                       \
447                 ".set\tpop\n"                       \
448                 "10:\n\t"                           \
449                 ".insn\n\t"                         \
450                 ".section\t.fixup,\"ax\"\n\t"       \
451                 "11:\tli\t%1, %3\n\t"               \
452                 "j\t10b\n\t"                        \
453                 ".previous\n\t"                     \
454                 ".section\t__ex_table,\"a\"\n\t"    \
455                 STR(PTR_WD)"\t1b, 11b\n\t"          \
456                 STR(PTR_WD)"\t2b, 11b\n\t"          \
457                 STR(PTR_WD)"\t3b, 11b\n\t"          \
458                 STR(PTR_WD)"\t4b, 11b\n\t"          \
459                 ".previous"                         \
460                 : "=&r" (value), "=r" (res)         \
461                 : "r" (addr), "i" (-EFAULT));       \
462 } while (0)
463
464 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
465
466
467 #define  _LoadHWU(addr, value, res, type) \
468 do {                                                \
469         __asm__ __volatile__ (                      \
470                 ".set\tnoat\n"                      \
471                 "1:\t"type##_lbu("%0", "1(%2)")"\n" \
472                 "2:\t"type##_lbu("$1", "0(%2)")"\n\t"\
473                 "sll\t%0, 0x8\n\t"                  \
474                 "or\t%0, $1\n\t"                    \
475                 "li\t%1, 0\n"                       \
476                 "3:\n\t"                            \
477                 ".insn\n\t"                         \
478                 ".set\tat\n\t"                      \
479                 ".section\t.fixup,\"ax\"\n\t"       \
480                 "4:\tli\t%1, %3\n\t"                \
481                 "j\t3b\n\t"                         \
482                 ".previous\n\t"                     \
483                 ".section\t__ex_table,\"a\"\n\t"    \
484                 STR(PTR_WD)"\t1b, 4b\n\t"           \
485                 STR(PTR_WD)"\t2b, 4b\n\t"           \
486                 ".previous"                         \
487                 : "=&r" (value), "=r" (res)         \
488                 : "r" (addr), "i" (-EFAULT));       \
489 } while (0)
490
491 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR
492 #define  _LoadWU(addr, value, res, type)  \
493 do {                                                \
494         __asm__ __volatile__ (                      \
495                 "1:\t"type##_lwl("%0", "3(%2)")"\n" \
496                 "2:\t"type##_lwr("%0", "(%2)")"\n\t"\
497                 "dsll\t%0, %0, 32\n\t"              \
498                 "dsrl\t%0, %0, 32\n\t"              \
499                 "li\t%1, 0\n"                       \
500                 "3:\n\t"                            \
501                 ".insn\n\t"                         \
502                 "\t.section\t.fixup,\"ax\"\n\t"     \
503                 "4:\tli\t%1, %3\n\t"                \
504                 "j\t3b\n\t"                         \
505                 ".previous\n\t"                     \
506                 ".section\t__ex_table,\"a\"\n\t"    \
507                 STR(PTR_WD)"\t1b, 4b\n\t"           \
508                 STR(PTR_WD)"\t2b, 4b\n\t"           \
509                 ".previous"                         \
510                 : "=&r" (value), "=r" (res)         \
511                 : "r" (addr), "i" (-EFAULT));       \
512 } while (0)
513
514 #define  _LoadDW(addr, value, res)  \
515 do {                                                \
516         __asm__ __volatile__ (                      \
517                 "1:\tldl\t%0, 7(%2)\n"              \
518                 "2:\tldr\t%0, (%2)\n\t"             \
519                 "li\t%1, 0\n"                       \
520                 "3:\n\t"                            \
521                 ".insn\n\t"                         \
522                 "\t.section\t.fixup,\"ax\"\n\t"     \
523                 "4:\tli\t%1, %3\n\t"                \
524                 "j\t3b\n\t"                         \
525                 ".previous\n\t"                     \
526                 ".section\t__ex_table,\"a\"\n\t"    \
527                 STR(PTR_WD)"\t1b, 4b\n\t"           \
528                 STR(PTR_WD)"\t2b, 4b\n\t"           \
529                 ".previous"                         \
530                 : "=&r" (value), "=r" (res)         \
531                 : "r" (addr), "i" (-EFAULT));       \
532 } while (0)
533
534 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */
535 /* For CPUs without lwl and ldl instructions */
536 #define  _LoadWU(addr, value, res, type) \
537 do {                                                \
538         __asm__ __volatile__ (                      \
539                 ".set\tpush\n\t"                    \
540                 ".set\tnoat\n\t"                    \
541                 "1:"type##_lbu("%0", "3(%2)")"\n\t" \
542                 "2:"type##_lbu("$1", "2(%2)")"\n\t" \
543                 "sll\t%0, 0x8\n\t"                  \
544                 "or\t%0, $1\n\t"                    \
545                 "3:"type##_lbu("$1", "1(%2)")"\n\t" \
546                 "sll\t%0, 0x8\n\t"                  \
547                 "or\t%0, $1\n\t"                    \
548                 "4:"type##_lbu("$1", "0(%2)")"\n\t" \
549                 "sll\t%0, 0x8\n\t"                  \
550                 "or\t%0, $1\n\t"                    \
551                 "li\t%1, 0\n"                       \
552                 ".set\tpop\n"                       \
553                 "10:\n\t"                           \
554                 ".insn\n\t"                         \
555                 ".section\t.fixup,\"ax\"\n\t"       \
556                 "11:\tli\t%1, %3\n\t"               \
557                 "j\t10b\n\t"                        \
558                 ".previous\n\t"                     \
559                 ".section\t__ex_table,\"a\"\n\t"    \
560                 STR(PTR_WD)"\t1b, 11b\n\t"          \
561                 STR(PTR_WD)"\t2b, 11b\n\t"          \
562                 STR(PTR_WD)"\t3b, 11b\n\t"          \
563                 STR(PTR_WD)"\t4b, 11b\n\t"          \
564                 ".previous"                         \
565                 : "=&r" (value), "=r" (res)         \
566                 : "r" (addr), "i" (-EFAULT));       \
567 } while (0)
568
569 #define  _LoadDW(addr, value, res)  \
570 do {                                                \
571         __asm__ __volatile__ (                      \
572                 ".set\tpush\n\t"                    \
573                 ".set\tnoat\n\t"                    \
574                 "1:lb\t%0, 7(%2)\n\t"               \
575                 "2:lbu\t$1, 6(%2)\n\t"              \
576                 "dsll\t%0, 0x8\n\t"                 \
577                 "or\t%0, $1\n\t"                    \
578                 "3:lbu\t$1, 5(%2)\n\t"              \
579                 "dsll\t%0, 0x8\n\t"                 \
580                 "or\t%0, $1\n\t"                    \
581                 "4:lbu\t$1, 4(%2)\n\t"              \
582                 "dsll\t%0, 0x8\n\t"                 \
583                 "or\t%0, $1\n\t"                    \
584                 "5:lbu\t$1, 3(%2)\n\t"              \
585                 "dsll\t%0, 0x8\n\t"                 \
586                 "or\t%0, $1\n\t"                    \
587                 "6:lbu\t$1, 2(%2)\n\t"              \
588                 "dsll\t%0, 0x8\n\t"                 \
589                 "or\t%0, $1\n\t"                    \
590                 "7:lbu\t$1, 1(%2)\n\t"              \
591                 "dsll\t%0, 0x8\n\t"                 \
592                 "or\t%0, $1\n\t"                    \
593                 "8:lbu\t$1, 0(%2)\n\t"              \
594                 "dsll\t%0, 0x8\n\t"                 \
595                 "or\t%0, $1\n\t"                    \
596                 "li\t%1, 0\n"                       \
597                 ".set\tpop\n\t"                     \
598                 "10:\n\t"                           \
599                 ".insn\n\t"                         \
600                 ".section\t.fixup,\"ax\"\n\t"       \
601                 "11:\tli\t%1, %3\n\t"               \
602                 "j\t10b\n\t"                        \
603                 ".previous\n\t"                     \
604                 ".section\t__ex_table,\"a\"\n\t"    \
605                 STR(PTR_WD)"\t1b, 11b\n\t"          \
606                 STR(PTR_WD)"\t2b, 11b\n\t"          \
607                 STR(PTR_WD)"\t3b, 11b\n\t"          \
608                 STR(PTR_WD)"\t4b, 11b\n\t"          \
609                 STR(PTR_WD)"\t5b, 11b\n\t"          \
610                 STR(PTR_WD)"\t6b, 11b\n\t"          \
611                 STR(PTR_WD)"\t7b, 11b\n\t"          \
612                 STR(PTR_WD)"\t8b, 11b\n\t"          \
613                 ".previous"                         \
614                 : "=&r" (value), "=r" (res)         \
615                 : "r" (addr), "i" (-EFAULT));       \
616 } while (0)
617 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
618
619 #define  _StoreHW(addr, value, res, type) \
620 do {                                                 \
621         __asm__ __volatile__ (                      \
622                 ".set\tnoat\n"                      \
623                 "1:\t"type##_sb("%1", "0(%2)")"\n"  \
624                 "srl\t$1,%1, 0x8\n"                 \
625                 "2:\t"type##_sb("$1", "1(%2)")"\n"  \
626                 ".set\tat\n\t"                      \
627                 "li\t%0, 0\n"                       \
628                 "3:\n\t"                            \
629                 ".insn\n\t"                         \
630                 ".section\t.fixup,\"ax\"\n\t"       \
631                 "4:\tli\t%0, %3\n\t"                \
632                 "j\t3b\n\t"                         \
633                 ".previous\n\t"                     \
634                 ".section\t__ex_table,\"a\"\n\t"    \
635                 STR(PTR_WD)"\t1b, 4b\n\t"           \
636                 STR(PTR_WD)"\t2b, 4b\n\t"           \
637                 ".previous"                         \
638                 : "=r" (res)                        \
639                 : "r" (value), "r" (addr), "i" (-EFAULT));\
640 } while (0)
641
642 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR
643 #define  _StoreW(addr, value, res, type)  \
644 do {                                                \
645         __asm__ __volatile__ (                      \
646                 "1:\t"type##_swl("%1", "3(%2)")"\n" \
647                 "2:\t"type##_swr("%1", "(%2)")"\n\t"\
648                 "li\t%0, 0\n"                       \
649                 "3:\n\t"                            \
650                 ".insn\n\t"                         \
651                 ".section\t.fixup,\"ax\"\n\t"       \
652                 "4:\tli\t%0, %3\n\t"                \
653                 "j\t3b\n\t"                         \
654                 ".previous\n\t"                     \
655                 ".section\t__ex_table,\"a\"\n\t"    \
656                 STR(PTR_WD)"\t1b, 4b\n\t"           \
657                 STR(PTR_WD)"\t2b, 4b\n\t"           \
658                 ".previous"                         \
659                 : "=r" (res)                                \
660                 : "r" (value), "r" (addr), "i" (-EFAULT));  \
661 } while (0)
662
663 #define  _StoreDW(addr, value, res) \
664 do {                                                \
665         __asm__ __volatile__ (                      \
666                 "1:\tsdl\t%1, 7(%2)\n"              \
667                 "2:\tsdr\t%1, (%2)\n\t"             \
668                 "li\t%0, 0\n"                       \
669                 "3:\n\t"                            \
670                 ".insn\n\t"                         \
671                 ".section\t.fixup,\"ax\"\n\t"       \
672                 "4:\tli\t%0, %3\n\t"                \
673                 "j\t3b\n\t"                         \
674                 ".previous\n\t"                     \
675                 ".section\t__ex_table,\"a\"\n\t"    \
676                 STR(PTR_WD)"\t1b, 4b\n\t"           \
677                 STR(PTR_WD)"\t2b, 4b\n\t"           \
678                 ".previous"                         \
679                 : "=r" (res)                                \
680                 : "r" (value), "r" (addr), "i" (-EFAULT));  \
681 } while (0)
682
683 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */
684 /* For CPUs without swl and sdl instructions */
685 #define  _StoreW(addr, value, res, type)  \
686 do {                                                \
687         __asm__ __volatile__ (                      \
688                 ".set\tpush\n\t"                    \
689                 ".set\tnoat\n\t"                    \
690                 "1:"type##_sb("%1", "0(%2)")"\n\t"  \
691                 "srl\t$1, %1, 0x8\n\t"              \
692                 "2:"type##_sb("$1", "1(%2)")"\n\t"  \
693                 "srl\t$1, $1,  0x8\n\t"             \
694                 "3:"type##_sb("$1", "2(%2)")"\n\t"  \
695                 "srl\t$1, $1, 0x8\n\t"              \
696                 "4:"type##_sb("$1", "3(%2)")"\n\t"  \
697                 ".set\tpop\n\t"                     \
698                 "li\t%0, 0\n"                       \
699                 "10:\n\t"                           \
700                 ".insn\n\t"                         \
701                 ".section\t.fixup,\"ax\"\n\t"       \
702                 "11:\tli\t%0, %3\n\t"               \
703                 "j\t10b\n\t"                        \
704                 ".previous\n\t"                     \
705                 ".section\t__ex_table,\"a\"\n\t"    \
706                 STR(PTR_WD)"\t1b, 11b\n\t"          \
707                 STR(PTR_WD)"\t2b, 11b\n\t"          \
708                 STR(PTR_WD)"\t3b, 11b\n\t"          \
709                 STR(PTR_WD)"\t4b, 11b\n\t"          \
710                 ".previous"                         \
711                 : "=&r" (res)                               \
712                 : "r" (value), "r" (addr), "i" (-EFAULT)    \
713                 : "memory");                                \
714 } while (0)
715
716 #define  _StoreDW(addr, value, res) \
717 do {                                                \
718         __asm__ __volatile__ (                      \
719                 ".set\tpush\n\t"                    \
720                 ".set\tnoat\n\t"                    \
721                 "1:sb\t%1, 0(%2)\n\t"               \
722                 "dsrl\t$1, %1, 0x8\n\t"             \
723                 "2:sb\t$1, 1(%2)\n\t"               \
724                 "dsrl\t$1, $1, 0x8\n\t"             \
725                 "3:sb\t$1, 2(%2)\n\t"               \
726                 "dsrl\t$1, $1, 0x8\n\t"             \
727                 "4:sb\t$1, 3(%2)\n\t"               \
728                 "dsrl\t$1, $1, 0x8\n\t"             \
729                 "5:sb\t$1, 4(%2)\n\t"               \
730                 "dsrl\t$1, $1, 0x8\n\t"             \
731                 "6:sb\t$1, 5(%2)\n\t"               \
732                 "dsrl\t$1, $1, 0x8\n\t"             \
733                 "7:sb\t$1, 6(%2)\n\t"               \
734                 "dsrl\t$1, $1, 0x8\n\t"             \
735                 "8:sb\t$1, 7(%2)\n\t"               \
736                 "dsrl\t$1, $1, 0x8\n\t"             \
737                 ".set\tpop\n\t"                     \
738                 "li\t%0, 0\n"                       \
739                 "10:\n\t"                           \
740                 ".insn\n\t"                         \
741                 ".section\t.fixup,\"ax\"\n\t"       \
742                 "11:\tli\t%0, %3\n\t"               \
743                 "j\t10b\n\t"                        \
744                 ".previous\n\t"                     \
745                 ".section\t__ex_table,\"a\"\n\t"    \
746                 STR(PTR_WD)"\t1b, 11b\n\t"          \
747                 STR(PTR_WD)"\t2b, 11b\n\t"          \
748                 STR(PTR_WD)"\t3b, 11b\n\t"          \
749                 STR(PTR_WD)"\t4b, 11b\n\t"          \
750                 STR(PTR_WD)"\t5b, 11b\n\t"          \
751                 STR(PTR_WD)"\t6b, 11b\n\t"          \
752                 STR(PTR_WD)"\t7b, 11b\n\t"          \
753                 STR(PTR_WD)"\t8b, 11b\n\t"          \
754                 ".previous"                         \
755                 : "=&r" (res)                               \
756                 : "r" (value), "r" (addr), "i" (-EFAULT)    \
757                 : "memory");                                \
758 } while (0)
759
760 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
761 #endif
762
763 #define LoadHWU(addr, value, res)       _LoadHWU(addr, value, res, kernel)
764 #define LoadHWUE(addr, value, res)      _LoadHWU(addr, value, res, user)
765 #define LoadWU(addr, value, res)        _LoadWU(addr, value, res, kernel)
766 #define LoadWUE(addr, value, res)       _LoadWU(addr, value, res, user)
767 #define LoadHW(addr, value, res)        _LoadHW(addr, value, res, kernel)
768 #define LoadHWE(addr, value, res)       _LoadHW(addr, value, res, user)
769 #define LoadW(addr, value, res)         _LoadW(addr, value, res, kernel)
770 #define LoadWE(addr, value, res)        _LoadW(addr, value, res, user)
771 #define LoadDW(addr, value, res)        _LoadDW(addr, value, res)
772
773 #define StoreHW(addr, value, res)       _StoreHW(addr, value, res, kernel)
774 #define StoreHWE(addr, value, res)      _StoreHW(addr, value, res, user)
775 #define StoreW(addr, value, res)        _StoreW(addr, value, res, kernel)
776 #define StoreWE(addr, value, res)       _StoreW(addr, value, res, user)
777 #define StoreDW(addr, value, res)       _StoreDW(addr, value, res)
778
779 #endif /* _ASM_MIPS_UNALIGNED_EMUL_H */