xref: /openbmc/linux/arch/mips/include/asm/inst.h (revision 59bd128a412702931afaf758af6b640e3528d1b5)
1 /*
2  * Format of an instruction in memory.
3  *
4  * This file is subject to the terms and conditions of the GNU General Public
5  * License.  See the file "COPYING" in the main directory of this archive
6  * for more details.
7  *
8  * Copyright (C) 1996, 2000 by Ralf Baechle
9  * Copyright (C) 2006 by Thiemo Seufer
10  */
11 #ifndef _ASM_INST_H
12 #define _ASM_INST_H
13 
14 #include <asm/asm.h>
15 #include <uapi/asm/inst.h>
16 
17 /* HACHACHAHCAHC ...  */
18 
19 /* In case some other massaging is needed, keep MIPSInst as wrapper */
20 
21 #define MIPSInst(x) x
22 
23 #define I_OPCODE_SFT	26
24 #define MIPSInst_OPCODE(x) (MIPSInst(x) >> I_OPCODE_SFT)
25 
26 #define I_JTARGET_SFT	0
27 #define MIPSInst_JTARGET(x) (MIPSInst(x) & 0x03ffffff)
28 
29 #define I_RS_SFT	21
30 #define MIPSInst_RS(x) ((MIPSInst(x) & 0x03e00000) >> I_RS_SFT)
31 
32 #define I_RT_SFT	16
33 #define MIPSInst_RT(x) ((MIPSInst(x) & 0x001f0000) >> I_RT_SFT)
34 
35 #define I_IMM_SFT	0
36 #define MIPSInst_SIMM(x) ((int)((short)(MIPSInst(x) & 0xffff)))
37 #define MIPSInst_UIMM(x) (MIPSInst(x) & 0xffff)
38 
39 #define I_CACHEOP_SFT	18
40 #define MIPSInst_CACHEOP(x) ((MIPSInst(x) & 0x001c0000) >> I_CACHEOP_SFT)
41 
42 #define I_CACHESEL_SFT	16
43 #define MIPSInst_CACHESEL(x) ((MIPSInst(x) & 0x00030000) >> I_CACHESEL_SFT)
44 
45 #define I_RD_SFT	11
46 #define MIPSInst_RD(x) ((MIPSInst(x) & 0x0000f800) >> I_RD_SFT)
47 
48 #define I_RE_SFT	6
49 #define MIPSInst_RE(x) ((MIPSInst(x) & 0x000007c0) >> I_RE_SFT)
50 
51 #define I_FUNC_SFT	0
52 #define MIPSInst_FUNC(x) (MIPSInst(x) & 0x0000003f)
53 
54 #define I_FFMT_SFT	21
55 #define MIPSInst_FFMT(x) ((MIPSInst(x) & 0x01e00000) >> I_FFMT_SFT)
56 
57 #define I_FT_SFT	16
58 #define MIPSInst_FT(x) ((MIPSInst(x) & 0x001f0000) >> I_FT_SFT)
59 
60 #define I_FS_SFT	11
61 #define MIPSInst_FS(x) ((MIPSInst(x) & 0x0000f800) >> I_FS_SFT)
62 
63 #define I_FD_SFT	6
64 #define MIPSInst_FD(x) ((MIPSInst(x) & 0x000007c0) >> I_FD_SFT)
65 
66 #define I_FR_SFT	21
67 #define MIPSInst_FR(x) ((MIPSInst(x) & 0x03e00000) >> I_FR_SFT)
68 
69 #define I_FMA_FUNC_SFT	2
70 #define MIPSInst_FMA_FUNC(x) ((MIPSInst(x) & 0x0000003c) >> I_FMA_FUNC_SFT)
71 
72 #define I_FMA_FFMT_SFT	0
73 #define MIPSInst_FMA_FFMT(x) (MIPSInst(x) & 0x00000003)
74 
75 typedef unsigned int mips_instruction;
76 
77 /* microMIPS instruction decode structure. Do NOT export!!! */
78 struct mm_decoded_insn {
79 	mips_instruction insn;
80 	mips_instruction next_insn;
81 	int pc_inc;
82 	int next_pc_inc;
83 	int micro_mips_mode;
84 };
85 
86 /* Recode table from 16-bit register notation to 32-bit GPR. Do NOT export!!! */
87 extern const int reg16to32[];
88 
89 #ifdef __BIG_ENDIAN
90 #define  _LoadHW(addr, value, res, type)  \
91 do {                                                \
92 	__asm__ __volatile__ (".set\tnoat\n"        \
93 		"1:\t"type##_lb("%0", "0(%2)")"\n"  \
94 		"2:\t"type##_lbu("$1", "1(%2)")"\n\t"\
95 		"sll\t%0, 0x8\n\t"                  \
96 		"or\t%0, $1\n\t"                    \
97 		"li\t%1, 0\n"                       \
98 		"3:\t.set\tat\n\t"                  \
99 		".insn\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)"\t1b, 4b\n\t"              \
106 		STR(PTR)"\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  _LoadW(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 		"li\t%1, 0\n"                       \
119 		"3:\n\t"                            \
120 		".insn\n\t"                         \
121 		".section\t.fixup,\"ax\"\n\t"       \
122 		"4:\tli\t%1, %3\n\t"                \
123 		"j\t3b\n\t"                         \
124 		".previous\n\t"                     \
125 		".section\t__ex_table,\"a\"\n\t"    \
126 		STR(PTR)"\t1b, 4b\n\t"              \
127 		STR(PTR)"\t2b, 4b\n\t"              \
128 		".previous"                         \
129 		: "=&r" (value), "=r" (res)         \
130 		: "r" (addr), "i" (-EFAULT));       \
131 } while (0)
132 
133 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */
134 /* For CPUs without lwl instruction */
135 #define  _LoadW(addr, value, res, type) \
136 do {                                                \
137 	__asm__ __volatile__ (			    \
138 		".set\tpush\n"			    \
139 		".set\tnoat\n\t"		    \
140 		"1:"type##_lb("%0", "0(%2)")"\n\t"  \
141 		"2:"type##_lbu("$1", "1(%2)")"\n\t" \
142 		"sll\t%0, 0x8\n\t"		    \
143 		"or\t%0, $1\n\t"		    \
144 		"3:"type##_lbu("$1", "2(%2)")"\n\t" \
145 		"sll\t%0, 0x8\n\t"		    \
146 		"or\t%0, $1\n\t"		    \
147 		"4:"type##_lbu("$1", "3(%2)")"\n\t" \
148 		"sll\t%0, 0x8\n\t"		    \
149 		"or\t%0, $1\n\t"		    \
150 		"li\t%1, 0\n"			    \
151 		".set\tpop\n"			    \
152 		"10:\n\t"			    \
153 		".insn\n\t"			    \
154 		".section\t.fixup,\"ax\"\n\t"	    \
155 		"11:\tli\t%1, %3\n\t"		    \
156 		"j\t10b\n\t"			    \
157 		".previous\n\t"			    \
158 		".section\t__ex_table,\"a\"\n\t"    \
159 		STR(PTR)"\t1b, 11b\n\t"		    \
160 		STR(PTR)"\t2b, 11b\n\t"		    \
161 		STR(PTR)"\t3b, 11b\n\t"		    \
162 		STR(PTR)"\t4b, 11b\n\t"		    \
163 		".previous"			    \
164 		: "=&r" (value), "=r" (res)	    \
165 		: "r" (addr), "i" (-EFAULT));       \
166 } while (0)
167 
168 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
169 
170 #define  _LoadHWU(addr, value, res, type) \
171 do {                                                \
172 	__asm__ __volatile__ (                      \
173 		".set\tnoat\n"                      \
174 		"1:\t"type##_lbu("%0", "0(%2)")"\n" \
175 		"2:\t"type##_lbu("$1", "1(%2)")"\n\t"\
176 		"sll\t%0, 0x8\n\t"                  \
177 		"or\t%0, $1\n\t"                    \
178 		"li\t%1, 0\n"                       \
179 		"3:\n\t"                            \
180 		".insn\n\t"                         \
181 		".set\tat\n\t"                      \
182 		".section\t.fixup,\"ax\"\n\t"       \
183 		"4:\tli\t%1, %3\n\t"                \
184 		"j\t3b\n\t"                         \
185 		".previous\n\t"                     \
186 		".section\t__ex_table,\"a\"\n\t"    \
187 		STR(PTR)"\t1b, 4b\n\t"              \
188 		STR(PTR)"\t2b, 4b\n\t"              \
189 		".previous"                         \
190 		: "=&r" (value), "=r" (res)         \
191 		: "r" (addr), "i" (-EFAULT));       \
192 } while (0)
193 
194 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR
195 #define  _LoadWU(addr, value, res, type)  \
196 do {                                                \
197 	__asm__ __volatile__ (                      \
198 		"1:\t"type##_lwl("%0", "(%2)")"\n"  \
199 		"2:\t"type##_lwr("%0", "3(%2)")"\n\t"\
200 		"dsll\t%0, %0, 32\n\t"              \
201 		"dsrl\t%0, %0, 32\n\t"              \
202 		"li\t%1, 0\n"                       \
203 		"3:\n\t"                            \
204 		".insn\n\t"                         \
205 		"\t.section\t.fixup,\"ax\"\n\t"     \
206 		"4:\tli\t%1, %3\n\t"                \
207 		"j\t3b\n\t"                         \
208 		".previous\n\t"                     \
209 		".section\t__ex_table,\"a\"\n\t"    \
210 		STR(PTR)"\t1b, 4b\n\t"              \
211 		STR(PTR)"\t2b, 4b\n\t"              \
212 		".previous"                         \
213 		: "=&r" (value), "=r" (res)         \
214 		: "r" (addr), "i" (-EFAULT));       \
215 } while (0)
216 
217 #define  _LoadDW(addr, value, res)  \
218 do {                                                \
219 	__asm__ __volatile__ (                      \
220 		"1:\tldl\t%0, (%2)\n"               \
221 		"2:\tldr\t%0, 7(%2)\n\t"            \
222 		"li\t%1, 0\n"                       \
223 		"3:\n\t"                            \
224 		".insn\n\t"                         \
225 		"\t.section\t.fixup,\"ax\"\n\t"     \
226 		"4:\tli\t%1, %3\n\t"                \
227 		"j\t3b\n\t"                         \
228 		".previous\n\t"                     \
229 		".section\t__ex_table,\"a\"\n\t"    \
230 		STR(PTR)"\t1b, 4b\n\t"              \
231 		STR(PTR)"\t2b, 4b\n\t"              \
232 		".previous"                         \
233 		: "=&r" (value), "=r" (res)         \
234 		: "r" (addr), "i" (-EFAULT));       \
235 } while (0)
236 
237 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */
238 /* For CPUs without lwl and ldl instructions */
239 #define  _LoadWU(addr, value, res, type) \
240 do {                                                \
241 	__asm__ __volatile__ (			    \
242 		".set\tpush\n\t"		    \
243 		".set\tnoat\n\t"		    \
244 		"1:"type##_lbu("%0", "0(%2)")"\n\t" \
245 		"2:"type##_lbu("$1", "1(%2)")"\n\t" \
246 		"sll\t%0, 0x8\n\t"		    \
247 		"or\t%0, $1\n\t"		    \
248 		"3:"type##_lbu("$1", "2(%2)")"\n\t" \
249 		"sll\t%0, 0x8\n\t"		    \
250 		"or\t%0, $1\n\t"		    \
251 		"4:"type##_lbu("$1", "3(%2)")"\n\t" \
252 		"sll\t%0, 0x8\n\t"		    \
253 		"or\t%0, $1\n\t"		    \
254 		"li\t%1, 0\n"			    \
255 		".set\tpop\n"			    \
256 		"10:\n\t"			    \
257 		".insn\n\t"			    \
258 		".section\t.fixup,\"ax\"\n\t"	    \
259 		"11:\tli\t%1, %3\n\t"		    \
260 		"j\t10b\n\t"			    \
261 		".previous\n\t"			    \
262 		".section\t__ex_table,\"a\"\n\t"    \
263 		STR(PTR)"\t1b, 11b\n\t"		    \
264 		STR(PTR)"\t2b, 11b\n\t"		    \
265 		STR(PTR)"\t3b, 11b\n\t"		    \
266 		STR(PTR)"\t4b, 11b\n\t"		    \
267 		".previous"			    \
268 		: "=&r" (value), "=r" (res)	    \
269 		: "r" (addr), "i" (-EFAULT));       \
270 } while (0)
271 
272 #define  _LoadDW(addr, value, res)  \
273 do {                                                \
274 	__asm__ __volatile__ (			    \
275 		".set\tpush\n\t"		    \
276 		".set\tnoat\n\t"		    \
277 		"1:lb\t%0, 0(%2)\n\t"		    \
278 		"2:lbu\t $1, 1(%2)\n\t"		    \
279 		"dsll\t%0, 0x8\n\t"		    \
280 		"or\t%0, $1\n\t"		    \
281 		"3:lbu\t$1, 2(%2)\n\t"		    \
282 		"dsll\t%0, 0x8\n\t"		    \
283 		"or\t%0, $1\n\t"		    \
284 		"4:lbu\t$1, 3(%2)\n\t"		    \
285 		"dsll\t%0, 0x8\n\t"		    \
286 		"or\t%0, $1\n\t"		    \
287 		"5:lbu\t$1, 4(%2)\n\t"		    \
288 		"dsll\t%0, 0x8\n\t"		    \
289 		"or\t%0, $1\n\t"		    \
290 		"6:lbu\t$1, 5(%2)\n\t"		    \
291 		"dsll\t%0, 0x8\n\t"		    \
292 		"or\t%0, $1\n\t"		    \
293 		"7:lbu\t$1, 6(%2)\n\t"		    \
294 		"dsll\t%0, 0x8\n\t"		    \
295 		"or\t%0, $1\n\t"		    \
296 		"8:lbu\t$1, 7(%2)\n\t"		    \
297 		"dsll\t%0, 0x8\n\t"		    \
298 		"or\t%0, $1\n\t"		    \
299 		"li\t%1, 0\n"			    \
300 		".set\tpop\n\t"			    \
301 		"10:\n\t"			    \
302 		".insn\n\t"			    \
303 		".section\t.fixup,\"ax\"\n\t"	    \
304 		"11:\tli\t%1, %3\n\t"		    \
305 		"j\t10b\n\t"			    \
306 		".previous\n\t"			    \
307 		".section\t__ex_table,\"a\"\n\t"    \
308 		STR(PTR)"\t1b, 11b\n\t"		    \
309 		STR(PTR)"\t2b, 11b\n\t"		    \
310 		STR(PTR)"\t3b, 11b\n\t"		    \
311 		STR(PTR)"\t4b, 11b\n\t"		    \
312 		STR(PTR)"\t5b, 11b\n\t"		    \
313 		STR(PTR)"\t6b, 11b\n\t"		    \
314 		STR(PTR)"\t7b, 11b\n\t"		    \
315 		STR(PTR)"\t8b, 11b\n\t"		    \
316 		".previous"			    \
317 		: "=&r" (value), "=r" (res)	    \
318 		: "r" (addr), "i" (-EFAULT));       \
319 } while (0)
320 
321 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
322 
323 
324 #define  _StoreHW(addr, value, res, type) \
325 do {                                                \
326 	__asm__ __volatile__ (                      \
327 		".set\tnoat\n"                      \
328 		"1:\t"type##_sb("%1", "1(%2)")"\n"  \
329 		"srl\t$1, %1, 0x8\n"                \
330 		"2:\t"type##_sb("$1", "0(%2)")"\n"  \
331 		".set\tat\n\t"                      \
332 		"li\t%0, 0\n"                       \
333 		"3:\n\t"                            \
334 		".insn\n\t"                         \
335 		".section\t.fixup,\"ax\"\n\t"       \
336 		"4:\tli\t%0, %3\n\t"                \
337 		"j\t3b\n\t"                         \
338 		".previous\n\t"                     \
339 		".section\t__ex_table,\"a\"\n\t"    \
340 		STR(PTR)"\t1b, 4b\n\t"              \
341 		STR(PTR)"\t2b, 4b\n\t"              \
342 		".previous"                         \
343 		: "=r" (res)                        \
344 		: "r" (value), "r" (addr), "i" (-EFAULT));\
345 } while (0)
346 
347 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR
348 #define  _StoreW(addr, value, res, type)  \
349 do {                                                \
350 	__asm__ __volatile__ (                      \
351 		"1:\t"type##_swl("%1", "(%2)")"\n"  \
352 		"2:\t"type##_swr("%1", "3(%2)")"\n\t"\
353 		"li\t%0, 0\n"                       \
354 		"3:\n\t"                            \
355 		".insn\n\t"                         \
356 		".section\t.fixup,\"ax\"\n\t"       \
357 		"4:\tli\t%0, %3\n\t"                \
358 		"j\t3b\n\t"                         \
359 		".previous\n\t"                     \
360 		".section\t__ex_table,\"a\"\n\t"    \
361 		STR(PTR)"\t1b, 4b\n\t"              \
362 		STR(PTR)"\t2b, 4b\n\t"              \
363 		".previous"                         \
364 		: "=r" (res)                                \
365 		: "r" (value), "r" (addr), "i" (-EFAULT));  \
366 } while (0)
367 
368 #define  _StoreDW(addr, value, res) \
369 do {                                                \
370 	__asm__ __volatile__ (                      \
371 		"1:\tsdl\t%1,(%2)\n"                \
372 		"2:\tsdr\t%1, 7(%2)\n\t"            \
373 		"li\t%0, 0\n"                       \
374 		"3:\n\t"                            \
375 		".insn\n\t"                         \
376 		".section\t.fixup,\"ax\"\n\t"       \
377 		"4:\tli\t%0, %3\n\t"                \
378 		"j\t3b\n\t"                         \
379 		".previous\n\t"                     \
380 		".section\t__ex_table,\"a\"\n\t"    \
381 		STR(PTR)"\t1b, 4b\n\t"              \
382 		STR(PTR)"\t2b, 4b\n\t"              \
383 		".previous"                         \
384 		: "=r" (res)                                \
385 		: "r" (value), "r" (addr), "i" (-EFAULT));  \
386 } while (0)
387 
388 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */
389 #define  _StoreW(addr, value, res, type)  \
390 do {                                                \
391 	__asm__ __volatile__ (                      \
392 		".set\tpush\n\t"		    \
393 		".set\tnoat\n\t"		    \
394 		"1:"type##_sb("%1", "3(%2)")"\n\t"  \
395 		"srl\t$1, %1, 0x8\n\t"		    \
396 		"2:"type##_sb("$1", "2(%2)")"\n\t"  \
397 		"srl\t$1, $1,  0x8\n\t"		    \
398 		"3:"type##_sb("$1", "1(%2)")"\n\t"  \
399 		"srl\t$1, $1, 0x8\n\t"		    \
400 		"4:"type##_sb("$1", "0(%2)")"\n\t"  \
401 		".set\tpop\n\t"			    \
402 		"li\t%0, 0\n"			    \
403 		"10:\n\t"			    \
404 		".insn\n\t"			    \
405 		".section\t.fixup,\"ax\"\n\t"	    \
406 		"11:\tli\t%0, %3\n\t"		    \
407 		"j\t10b\n\t"			    \
408 		".previous\n\t"			    \
409 		".section\t__ex_table,\"a\"\n\t"    \
410 		STR(PTR)"\t1b, 11b\n\t"		    \
411 		STR(PTR)"\t2b, 11b\n\t"		    \
412 		STR(PTR)"\t3b, 11b\n\t"		    \
413 		STR(PTR)"\t4b, 11b\n\t"		    \
414 		".previous"			    \
415 		: "=&r" (res)				    \
416 		: "r" (value), "r" (addr), "i" (-EFAULT)    \
417 		: "memory");                                \
418 } while (0)
419 
420 #define  _StoreDW(addr, value, res) \
421 do {                                                \
422 	__asm__ __volatile__ (                      \
423 		".set\tpush\n\t"		    \
424 		".set\tnoat\n\t"		    \
425 		"1:sb\t%1, 7(%2)\n\t"		    \
426 		"dsrl\t$1, %1, 0x8\n\t"		    \
427 		"2:sb\t$1, 6(%2)\n\t"		    \
428 		"dsrl\t$1, $1, 0x8\n\t"		    \
429 		"3:sb\t$1, 5(%2)\n\t"		    \
430 		"dsrl\t$1, $1, 0x8\n\t"		    \
431 		"4:sb\t$1, 4(%2)\n\t"		    \
432 		"dsrl\t$1, $1, 0x8\n\t"		    \
433 		"5:sb\t$1, 3(%2)\n\t"		    \
434 		"dsrl\t$1, $1, 0x8\n\t"		    \
435 		"6:sb\t$1, 2(%2)\n\t"		    \
436 		"dsrl\t$1, $1, 0x8\n\t"		    \
437 		"7:sb\t$1, 1(%2)\n\t"		    \
438 		"dsrl\t$1, $1, 0x8\n\t"		    \
439 		"8:sb\t$1, 0(%2)\n\t"		    \
440 		"dsrl\t$1, $1, 0x8\n\t"		    \
441 		".set\tpop\n\t"			    \
442 		"li\t%0, 0\n"			    \
443 		"10:\n\t"			    \
444 		".insn\n\t"			    \
445 		".section\t.fixup,\"ax\"\n\t"	    \
446 		"11:\tli\t%0, %3\n\t"		    \
447 		"j\t10b\n\t"			    \
448 		".previous\n\t"			    \
449 		".section\t__ex_table,\"a\"\n\t"    \
450 		STR(PTR)"\t1b, 11b\n\t"		    \
451 		STR(PTR)"\t2b, 11b\n\t"		    \
452 		STR(PTR)"\t3b, 11b\n\t"		    \
453 		STR(PTR)"\t4b, 11b\n\t"		    \
454 		STR(PTR)"\t5b, 11b\n\t"		    \
455 		STR(PTR)"\t6b, 11b\n\t"		    \
456 		STR(PTR)"\t7b, 11b\n\t"		    \
457 		STR(PTR)"\t8b, 11b\n\t"		    \
458 		".previous"			    \
459 		: "=&r" (res)				    \
460 		: "r" (value), "r" (addr), "i" (-EFAULT)    \
461 		: "memory");                                \
462 } while (0)
463 
464 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
465 
466 #else /* __BIG_ENDIAN */
467 
468 #define  _LoadHW(addr, value, res, type)  \
469 do {                                                \
470 	__asm__ __volatile__ (".set\tnoat\n"        \
471 		"1:\t"type##_lb("%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:\t.set\tat\n\t"                  \
477 		".insn\n\t"                         \
478 		".section\t.fixup,\"ax\"\n\t"       \
479 		"4:\tli\t%1, %3\n\t"                \
480 		"j\t3b\n\t"                         \
481 		".previous\n\t"                     \
482 		".section\t__ex_table,\"a\"\n\t"    \
483 		STR(PTR)"\t1b, 4b\n\t"              \
484 		STR(PTR)"\t2b, 4b\n\t"              \
485 		".previous"                         \
486 		: "=&r" (value), "=r" (res)         \
487 		: "r" (addr), "i" (-EFAULT));       \
488 } while (0)
489 
490 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR
491 #define  _LoadW(addr, value, res, type)   \
492 do {                                                \
493 	__asm__ __volatile__ (                      \
494 		"1:\t"type##_lwl("%0", "3(%2)")"\n" \
495 		"2:\t"type##_lwr("%0", "(%2)")"\n\t"\
496 		"li\t%1, 0\n"                       \
497 		"3:\n\t"                            \
498 		".insn\n\t"                         \
499 		".section\t.fixup,\"ax\"\n\t"       \
500 		"4:\tli\t%1, %3\n\t"                \
501 		"j\t3b\n\t"                         \
502 		".previous\n\t"                     \
503 		".section\t__ex_table,\"a\"\n\t"    \
504 		STR(PTR)"\t1b, 4b\n\t"              \
505 		STR(PTR)"\t2b, 4b\n\t"              \
506 		".previous"                         \
507 		: "=&r" (value), "=r" (res)         \
508 		: "r" (addr), "i" (-EFAULT));       \
509 } while (0)
510 
511 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */
512 /* For CPUs without lwl instruction */
513 #define  _LoadW(addr, value, res, type) \
514 do {                                                \
515 	__asm__ __volatile__ (			    \
516 		".set\tpush\n"			    \
517 		".set\tnoat\n\t"		    \
518 		"1:"type##_lb("%0", "3(%2)")"\n\t"  \
519 		"2:"type##_lbu("$1", "2(%2)")"\n\t" \
520 		"sll\t%0, 0x8\n\t"		    \
521 		"or\t%0, $1\n\t"		    \
522 		"3:"type##_lbu("$1", "1(%2)")"\n\t" \
523 		"sll\t%0, 0x8\n\t"		    \
524 		"or\t%0, $1\n\t"		    \
525 		"4:"type##_lbu("$1", "0(%2)")"\n\t" \
526 		"sll\t%0, 0x8\n\t"		    \
527 		"or\t%0, $1\n\t"		    \
528 		"li\t%1, 0\n"			    \
529 		".set\tpop\n"			    \
530 		"10:\n\t"			    \
531 		".insn\n\t"			    \
532 		".section\t.fixup,\"ax\"\n\t"	    \
533 		"11:\tli\t%1, %3\n\t"		    \
534 		"j\t10b\n\t"			    \
535 		".previous\n\t"			    \
536 		".section\t__ex_table,\"a\"\n\t"    \
537 		STR(PTR)"\t1b, 11b\n\t"		    \
538 		STR(PTR)"\t2b, 11b\n\t"		    \
539 		STR(PTR)"\t3b, 11b\n\t"		    \
540 		STR(PTR)"\t4b, 11b\n\t"		    \
541 		".previous"			    \
542 		: "=&r" (value), "=r" (res)	    \
543 		: "r" (addr), "i" (-EFAULT));       \
544 } while (0)
545 
546 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
547 
548 
549 #define  _LoadHWU(addr, value, res, type) \
550 do {                                                \
551 	__asm__ __volatile__ (                      \
552 		".set\tnoat\n"                      \
553 		"1:\t"type##_lbu("%0", "1(%2)")"\n" \
554 		"2:\t"type##_lbu("$1", "0(%2)")"\n\t"\
555 		"sll\t%0, 0x8\n\t"                  \
556 		"or\t%0, $1\n\t"                    \
557 		"li\t%1, 0\n"                       \
558 		"3:\n\t"                            \
559 		".insn\n\t"                         \
560 		".set\tat\n\t"                      \
561 		".section\t.fixup,\"ax\"\n\t"       \
562 		"4:\tli\t%1, %3\n\t"                \
563 		"j\t3b\n\t"                         \
564 		".previous\n\t"                     \
565 		".section\t__ex_table,\"a\"\n\t"    \
566 		STR(PTR)"\t1b, 4b\n\t"              \
567 		STR(PTR)"\t2b, 4b\n\t"              \
568 		".previous"                         \
569 		: "=&r" (value), "=r" (res)         \
570 		: "r" (addr), "i" (-EFAULT));       \
571 } while (0)
572 
573 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR
574 #define  _LoadWU(addr, value, res, type)  \
575 do {                                                \
576 	__asm__ __volatile__ (                      \
577 		"1:\t"type##_lwl("%0", "3(%2)")"\n" \
578 		"2:\t"type##_lwr("%0", "(%2)")"\n\t"\
579 		"dsll\t%0, %0, 32\n\t"              \
580 		"dsrl\t%0, %0, 32\n\t"              \
581 		"li\t%1, 0\n"                       \
582 		"3:\n\t"                            \
583 		".insn\n\t"                         \
584 		"\t.section\t.fixup,\"ax\"\n\t"     \
585 		"4:\tli\t%1, %3\n\t"                \
586 		"j\t3b\n\t"                         \
587 		".previous\n\t"                     \
588 		".section\t__ex_table,\"a\"\n\t"    \
589 		STR(PTR)"\t1b, 4b\n\t"              \
590 		STR(PTR)"\t2b, 4b\n\t"              \
591 		".previous"                         \
592 		: "=&r" (value), "=r" (res)         \
593 		: "r" (addr), "i" (-EFAULT));       \
594 } while (0)
595 
596 #define  _LoadDW(addr, value, res)  \
597 do {                                                \
598 	__asm__ __volatile__ (                      \
599 		"1:\tldl\t%0, 7(%2)\n"              \
600 		"2:\tldr\t%0, (%2)\n\t"             \
601 		"li\t%1, 0\n"                       \
602 		"3:\n\t"                            \
603 		".insn\n\t"                         \
604 		"\t.section\t.fixup,\"ax\"\n\t"     \
605 		"4:\tli\t%1, %3\n\t"                \
606 		"j\t3b\n\t"                         \
607 		".previous\n\t"                     \
608 		".section\t__ex_table,\"a\"\n\t"    \
609 		STR(PTR)"\t1b, 4b\n\t"              \
610 		STR(PTR)"\t2b, 4b\n\t"              \
611 		".previous"                         \
612 		: "=&r" (value), "=r" (res)         \
613 		: "r" (addr), "i" (-EFAULT));       \
614 } while (0)
615 
616 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */
617 /* For CPUs without lwl and ldl instructions */
618 #define  _LoadWU(addr, value, res, type) \
619 do {                                                \
620 	__asm__ __volatile__ (			    \
621 		".set\tpush\n\t"		    \
622 		".set\tnoat\n\t"		    \
623 		"1:"type##_lbu("%0", "3(%2)")"\n\t" \
624 		"2:"type##_lbu("$1", "2(%2)")"\n\t" \
625 		"sll\t%0, 0x8\n\t"		    \
626 		"or\t%0, $1\n\t"		    \
627 		"3:"type##_lbu("$1", "1(%2)")"\n\t" \
628 		"sll\t%0, 0x8\n\t"		    \
629 		"or\t%0, $1\n\t"		    \
630 		"4:"type##_lbu("$1", "0(%2)")"\n\t" \
631 		"sll\t%0, 0x8\n\t"		    \
632 		"or\t%0, $1\n\t"		    \
633 		"li\t%1, 0\n"			    \
634 		".set\tpop\n"			    \
635 		"10:\n\t"			    \
636 		".insn\n\t"			    \
637 		".section\t.fixup,\"ax\"\n\t"	    \
638 		"11:\tli\t%1, %3\n\t"		    \
639 		"j\t10b\n\t"			    \
640 		".previous\n\t"			    \
641 		".section\t__ex_table,\"a\"\n\t"    \
642 		STR(PTR)"\t1b, 11b\n\t"		    \
643 		STR(PTR)"\t2b, 11b\n\t"		    \
644 		STR(PTR)"\t3b, 11b\n\t"		    \
645 		STR(PTR)"\t4b, 11b\n\t"		    \
646 		".previous"			    \
647 		: "=&r" (value), "=r" (res)	    \
648 		: "r" (addr), "i" (-EFAULT));       \
649 } while (0)
650 
651 #define  _LoadDW(addr, value, res)  \
652 do {                                                \
653 	__asm__ __volatile__ (			    \
654 		".set\tpush\n\t"		    \
655 		".set\tnoat\n\t"		    \
656 		"1:lb\t%0, 7(%2)\n\t"		    \
657 		"2:lbu\t$1, 6(%2)\n\t"		    \
658 		"dsll\t%0, 0x8\n\t"		    \
659 		"or\t%0, $1\n\t"		    \
660 		"3:lbu\t$1, 5(%2)\n\t"		    \
661 		"dsll\t%0, 0x8\n\t"		    \
662 		"or\t%0, $1\n\t"		    \
663 		"4:lbu\t$1, 4(%2)\n\t"		    \
664 		"dsll\t%0, 0x8\n\t"		    \
665 		"or\t%0, $1\n\t"		    \
666 		"5:lbu\t$1, 3(%2)\n\t"		    \
667 		"dsll\t%0, 0x8\n\t"		    \
668 		"or\t%0, $1\n\t"		    \
669 		"6:lbu\t$1, 2(%2)\n\t"		    \
670 		"dsll\t%0, 0x8\n\t"		    \
671 		"or\t%0, $1\n\t"		    \
672 		"7:lbu\t$1, 1(%2)\n\t"		    \
673 		"dsll\t%0, 0x8\n\t"		    \
674 		"or\t%0, $1\n\t"		    \
675 		"8:lbu\t$1, 0(%2)\n\t"		    \
676 		"dsll\t%0, 0x8\n\t"		    \
677 		"or\t%0, $1\n\t"		    \
678 		"li\t%1, 0\n"			    \
679 		".set\tpop\n\t"			    \
680 		"10:\n\t"			    \
681 		".insn\n\t"			    \
682 		".section\t.fixup,\"ax\"\n\t"	    \
683 		"11:\tli\t%1, %3\n\t"		    \
684 		"j\t10b\n\t"			    \
685 		".previous\n\t"			    \
686 		".section\t__ex_table,\"a\"\n\t"    \
687 		STR(PTR)"\t1b, 11b\n\t"		    \
688 		STR(PTR)"\t2b, 11b\n\t"		    \
689 		STR(PTR)"\t3b, 11b\n\t"		    \
690 		STR(PTR)"\t4b, 11b\n\t"		    \
691 		STR(PTR)"\t5b, 11b\n\t"		    \
692 		STR(PTR)"\t6b, 11b\n\t"		    \
693 		STR(PTR)"\t7b, 11b\n\t"		    \
694 		STR(PTR)"\t8b, 11b\n\t"		    \
695 		".previous"			    \
696 		: "=&r" (value), "=r" (res)	    \
697 		: "r" (addr), "i" (-EFAULT));       \
698 } while (0)
699 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
700 
701 #define  _StoreHW(addr, value, res, type) \
702 do {                                                 \
703 	__asm__ __volatile__ (                      \
704 		".set\tnoat\n"                      \
705 		"1:\t"type##_sb("%1", "0(%2)")"\n"  \
706 		"srl\t$1,%1, 0x8\n"                 \
707 		"2:\t"type##_sb("$1", "1(%2)")"\n"  \
708 		".set\tat\n\t"                      \
709 		"li\t%0, 0\n"                       \
710 		"3:\n\t"                            \
711 		".insn\n\t"                         \
712 		".section\t.fixup,\"ax\"\n\t"       \
713 		"4:\tli\t%0, %3\n\t"                \
714 		"j\t3b\n\t"                         \
715 		".previous\n\t"                     \
716 		".section\t__ex_table,\"a\"\n\t"    \
717 		STR(PTR)"\t1b, 4b\n\t"              \
718 		STR(PTR)"\t2b, 4b\n\t"              \
719 		".previous"                         \
720 		: "=r" (res)                        \
721 		: "r" (value), "r" (addr), "i" (-EFAULT));\
722 } while (0)
723 
724 #ifndef CONFIG_CPU_NO_LOAD_STORE_LR
725 #define  _StoreW(addr, value, res, type)  \
726 do {                                                \
727 	__asm__ __volatile__ (                      \
728 		"1:\t"type##_swl("%1", "3(%2)")"\n" \
729 		"2:\t"type##_swr("%1", "(%2)")"\n\t"\
730 		"li\t%0, 0\n"                       \
731 		"3:\n\t"                            \
732 		".insn\n\t"                         \
733 		".section\t.fixup,\"ax\"\n\t"       \
734 		"4:\tli\t%0, %3\n\t"                \
735 		"j\t3b\n\t"                         \
736 		".previous\n\t"                     \
737 		".section\t__ex_table,\"a\"\n\t"    \
738 		STR(PTR)"\t1b, 4b\n\t"              \
739 		STR(PTR)"\t2b, 4b\n\t"              \
740 		".previous"                         \
741 		: "=r" (res)                                \
742 		: "r" (value), "r" (addr), "i" (-EFAULT));  \
743 } while (0)
744 
745 #define  _StoreDW(addr, value, res) \
746 do {                                                \
747 	__asm__ __volatile__ (                      \
748 		"1:\tsdl\t%1, 7(%2)\n"              \
749 		"2:\tsdr\t%1, (%2)\n\t"             \
750 		"li\t%0, 0\n"                       \
751 		"3:\n\t"                            \
752 		".insn\n\t"                         \
753 		".section\t.fixup,\"ax\"\n\t"       \
754 		"4:\tli\t%0, %3\n\t"                \
755 		"j\t3b\n\t"                         \
756 		".previous\n\t"                     \
757 		".section\t__ex_table,\"a\"\n\t"    \
758 		STR(PTR)"\t1b, 4b\n\t"              \
759 		STR(PTR)"\t2b, 4b\n\t"              \
760 		".previous"                         \
761 		: "=r" (res)                                \
762 		: "r" (value), "r" (addr), "i" (-EFAULT));  \
763 } while (0)
764 
765 #else /* CONFIG_CPU_NO_LOAD_STORE_LR */
766 /* For CPUs without swl and sdl instructions */
767 #define  _StoreW(addr, value, res, type)  \
768 do {                                                \
769 	__asm__ __volatile__ (                      \
770 		".set\tpush\n\t"		    \
771 		".set\tnoat\n\t"		    \
772 		"1:"type##_sb("%1", "0(%2)")"\n\t"  \
773 		"srl\t$1, %1, 0x8\n\t"		    \
774 		"2:"type##_sb("$1", "1(%2)")"\n\t"  \
775 		"srl\t$1, $1,  0x8\n\t"		    \
776 		"3:"type##_sb("$1", "2(%2)")"\n\t"  \
777 		"srl\t$1, $1, 0x8\n\t"		    \
778 		"4:"type##_sb("$1", "3(%2)")"\n\t"  \
779 		".set\tpop\n\t"			    \
780 		"li\t%0, 0\n"			    \
781 		"10:\n\t"			    \
782 		".insn\n\t"			    \
783 		".section\t.fixup,\"ax\"\n\t"	    \
784 		"11:\tli\t%0, %3\n\t"		    \
785 		"j\t10b\n\t"			    \
786 		".previous\n\t"			    \
787 		".section\t__ex_table,\"a\"\n\t"    \
788 		STR(PTR)"\t1b, 11b\n\t"		    \
789 		STR(PTR)"\t2b, 11b\n\t"		    \
790 		STR(PTR)"\t3b, 11b\n\t"		    \
791 		STR(PTR)"\t4b, 11b\n\t"		    \
792 		".previous"			    \
793 		: "=&r" (res)				    \
794 		: "r" (value), "r" (addr), "i" (-EFAULT)    \
795 		: "memory");                                \
796 } while (0)
797 
798 #define  _StoreDW(addr, value, res) \
799 do {                                                \
800 	__asm__ __volatile__ (                      \
801 		".set\tpush\n\t"		    \
802 		".set\tnoat\n\t"		    \
803 		"1:sb\t%1, 0(%2)\n\t"		    \
804 		"dsrl\t$1, %1, 0x8\n\t"		    \
805 		"2:sb\t$1, 1(%2)\n\t"		    \
806 		"dsrl\t$1, $1, 0x8\n\t"		    \
807 		"3:sb\t$1, 2(%2)\n\t"		    \
808 		"dsrl\t$1, $1, 0x8\n\t"		    \
809 		"4:sb\t$1, 3(%2)\n\t"		    \
810 		"dsrl\t$1, $1, 0x8\n\t"		    \
811 		"5:sb\t$1, 4(%2)\n\t"		    \
812 		"dsrl\t$1, $1, 0x8\n\t"		    \
813 		"6:sb\t$1, 5(%2)\n\t"		    \
814 		"dsrl\t$1, $1, 0x8\n\t"		    \
815 		"7:sb\t$1, 6(%2)\n\t"		    \
816 		"dsrl\t$1, $1, 0x8\n\t"		    \
817 		"8:sb\t$1, 7(%2)\n\t"		    \
818 		"dsrl\t$1, $1, 0x8\n\t"		    \
819 		".set\tpop\n\t"			    \
820 		"li\t%0, 0\n"			    \
821 		"10:\n\t"			    \
822 		".insn\n\t"			    \
823 		".section\t.fixup,\"ax\"\n\t"	    \
824 		"11:\tli\t%0, %3\n\t"		    \
825 		"j\t10b\n\t"			    \
826 		".previous\n\t"			    \
827 		".section\t__ex_table,\"a\"\n\t"    \
828 		STR(PTR)"\t1b, 11b\n\t"		    \
829 		STR(PTR)"\t2b, 11b\n\t"		    \
830 		STR(PTR)"\t3b, 11b\n\t"		    \
831 		STR(PTR)"\t4b, 11b\n\t"		    \
832 		STR(PTR)"\t5b, 11b\n\t"		    \
833 		STR(PTR)"\t6b, 11b\n\t"		    \
834 		STR(PTR)"\t7b, 11b\n\t"		    \
835 		STR(PTR)"\t8b, 11b\n\t"		    \
836 		".previous"			    \
837 		: "=&r" (res)				    \
838 		: "r" (value), "r" (addr), "i" (-EFAULT)    \
839 		: "memory");                                \
840 } while (0)
841 
842 #endif /* CONFIG_CPU_NO_LOAD_STORE_LR */
843 #endif
844 
845 #define LoadHWU(addr, value, res)	_LoadHWU(addr, value, res, kernel)
846 #define LoadHWUE(addr, value, res)	_LoadHWU(addr, value, res, user)
847 #define LoadWU(addr, value, res)	_LoadWU(addr, value, res, kernel)
848 #define LoadWUE(addr, value, res)	_LoadWU(addr, value, res, user)
849 #define LoadHW(addr, value, res)	_LoadHW(addr, value, res, kernel)
850 #define LoadHWE(addr, value, res)	_LoadHW(addr, value, res, user)
851 #define LoadW(addr, value, res)		_LoadW(addr, value, res, kernel)
852 #define LoadWE(addr, value, res)	_LoadW(addr, value, res, user)
853 #define LoadDW(addr, value, res)	_LoadDW(addr, value, res)
854 
855 #define StoreHW(addr, value, res)	_StoreHW(addr, value, res, kernel)
856 #define StoreHWE(addr, value, res)	_StoreHW(addr, value, res, user)
857 #define StoreW(addr, value, res)	_StoreW(addr, value, res, kernel)
858 #define StoreWE(addr, value, res)	_StoreW(addr, value, res, user)
859 #define StoreDW(addr, value, res)	_StoreDW(addr, value, res)
860 
861 #endif /* _ASM_INST_H */
862