xref: /linux/arch/mips/include/asm/unaligned-emul.h (revision 40d269c000bda9fcd276a0412a9cebd3f6e344c5)
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 */
780