diff options
Diffstat (limited to 'arch/mips/kernel/unaligned.c')
-rw-r--r-- | arch/mips/kernel/unaligned.c | 390 |
1 files changed, 386 insertions, 4 deletions
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index e11906dff885..bbb69695a0a1 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c | |||
@@ -129,6 +129,7 @@ extern void show_registers(struct pt_regs *regs); | |||
129 | : "=&r" (value), "=r" (res) \ | 129 | : "=&r" (value), "=r" (res) \ |
130 | : "r" (addr), "i" (-EFAULT)); | 130 | : "r" (addr), "i" (-EFAULT)); |
131 | 131 | ||
132 | #ifndef CONFIG_CPU_MIPSR6 | ||
132 | #define LoadW(addr, value, res) \ | 133 | #define LoadW(addr, value, res) \ |
133 | __asm__ __volatile__ ( \ | 134 | __asm__ __volatile__ ( \ |
134 | "1:\t"user_lwl("%0", "(%2)")"\n" \ | 135 | "1:\t"user_lwl("%0", "(%2)")"\n" \ |
@@ -146,6 +147,39 @@ extern void show_registers(struct pt_regs *regs); | |||
146 | ".previous" \ | 147 | ".previous" \ |
147 | : "=&r" (value), "=r" (res) \ | 148 | : "=&r" (value), "=r" (res) \ |
148 | : "r" (addr), "i" (-EFAULT)); | 149 | : "r" (addr), "i" (-EFAULT)); |
150 | #else | ||
151 | /* MIPSR6 has no lwl instruction */ | ||
152 | #define LoadW(addr, value, res) \ | ||
153 | __asm__ __volatile__ ( \ | ||
154 | ".set\tpush\n" \ | ||
155 | ".set\tnoat\n\t" \ | ||
156 | "1:"user_lb("%0", "0(%2)")"\n\t" \ | ||
157 | "2:"user_lbu("$1", "1(%2)")"\n\t" \ | ||
158 | "sll\t%0, 0x8\n\t" \ | ||
159 | "or\t%0, $1\n\t" \ | ||
160 | "3:"user_lbu("$1", "2(%2)")"\n\t" \ | ||
161 | "sll\t%0, 0x8\n\t" \ | ||
162 | "or\t%0, $1\n\t" \ | ||
163 | "4:"user_lbu("$1", "3(%2)")"\n\t" \ | ||
164 | "sll\t%0, 0x8\n\t" \ | ||
165 | "or\t%0, $1\n\t" \ | ||
166 | "li\t%1, 0\n" \ | ||
167 | ".set\tpop\n" \ | ||
168 | "10:\n\t" \ | ||
169 | ".insn\n\t" \ | ||
170 | ".section\t.fixup,\"ax\"\n\t" \ | ||
171 | "11:\tli\t%1, %3\n\t" \ | ||
172 | "j\t10b\n\t" \ | ||
173 | ".previous\n\t" \ | ||
174 | ".section\t__ex_table,\"a\"\n\t" \ | ||
175 | STR(PTR)"\t1b, 11b\n\t" \ | ||
176 | STR(PTR)"\t2b, 11b\n\t" \ | ||
177 | STR(PTR)"\t3b, 11b\n\t" \ | ||
178 | STR(PTR)"\t4b, 11b\n\t" \ | ||
179 | ".previous" \ | ||
180 | : "=&r" (value), "=r" (res) \ | ||
181 | : "r" (addr), "i" (-EFAULT)); | ||
182 | #endif /* CONFIG_CPU_MIPSR6 */ | ||
149 | 183 | ||
150 | #define LoadHWU(addr, value, res) \ | 184 | #define LoadHWU(addr, value, res) \ |
151 | __asm__ __volatile__ ( \ | 185 | __asm__ __volatile__ ( \ |
@@ -169,6 +203,7 @@ extern void show_registers(struct pt_regs *regs); | |||
169 | : "=&r" (value), "=r" (res) \ | 203 | : "=&r" (value), "=r" (res) \ |
170 | : "r" (addr), "i" (-EFAULT)); | 204 | : "r" (addr), "i" (-EFAULT)); |
171 | 205 | ||
206 | #ifndef CONFIG_CPU_MIPSR6 | ||
172 | #define LoadWU(addr, value, res) \ | 207 | #define LoadWU(addr, value, res) \ |
173 | __asm__ __volatile__ ( \ | 208 | __asm__ __volatile__ ( \ |
174 | "1:\t"user_lwl("%0", "(%2)")"\n" \ | 209 | "1:\t"user_lwl("%0", "(%2)")"\n" \ |
@@ -206,6 +241,87 @@ extern void show_registers(struct pt_regs *regs); | |||
206 | ".previous" \ | 241 | ".previous" \ |
207 | : "=&r" (value), "=r" (res) \ | 242 | : "=&r" (value), "=r" (res) \ |
208 | : "r" (addr), "i" (-EFAULT)); | 243 | : "r" (addr), "i" (-EFAULT)); |
244 | #else | ||
245 | /* MIPSR6 has not lwl and ldl instructions */ | ||
246 | #define LoadWU(addr, value, res) \ | ||
247 | __asm__ __volatile__ ( \ | ||
248 | ".set\tpush\n\t" \ | ||
249 | ".set\tnoat\n\t" \ | ||
250 | "1:"user_lbu("%0", "0(%2)")"\n\t" \ | ||
251 | "2:"user_lbu("$1", "1(%2)")"\n\t" \ | ||
252 | "sll\t%0, 0x8\n\t" \ | ||
253 | "or\t%0, $1\n\t" \ | ||
254 | "3:"user_lbu("$1", "2(%2)")"\n\t" \ | ||
255 | "sll\t%0, 0x8\n\t" \ | ||
256 | "or\t%0, $1\n\t" \ | ||
257 | "4:"user_lbu("$1", "3(%2)")"\n\t" \ | ||
258 | "sll\t%0, 0x8\n\t" \ | ||
259 | "or\t%0, $1\n\t" \ | ||
260 | "li\t%1, 0\n" \ | ||
261 | ".set\tpop\n" \ | ||
262 | "10:\n\t" \ | ||
263 | ".insn\n\t" \ | ||
264 | ".section\t.fixup,\"ax\"\n\t" \ | ||
265 | "11:\tli\t%1, %3\n\t" \ | ||
266 | "j\t10b\n\t" \ | ||
267 | ".previous\n\t" \ | ||
268 | ".section\t__ex_table,\"a\"\n\t" \ | ||
269 | STR(PTR)"\t1b, 11b\n\t" \ | ||
270 | STR(PTR)"\t2b, 11b\n\t" \ | ||
271 | STR(PTR)"\t3b, 11b\n\t" \ | ||
272 | STR(PTR)"\t4b, 11b\n\t" \ | ||
273 | ".previous" \ | ||
274 | : "=&r" (value), "=r" (res) \ | ||
275 | : "r" (addr), "i" (-EFAULT)); | ||
276 | |||
277 | #define LoadDW(addr, value, res) \ | ||
278 | __asm__ __volatile__ ( \ | ||
279 | ".set\tpush\n\t" \ | ||
280 | ".set\tnoat\n\t" \ | ||
281 | "1:lb\t%0, 0(%2)\n\t" \ | ||
282 | "2:lbu\t $1, 1(%2)\n\t" \ | ||
283 | "dsll\t%0, 0x8\n\t" \ | ||
284 | "or\t%0, $1\n\t" \ | ||
285 | "3:lbu\t$1, 2(%2)\n\t" \ | ||
286 | "dsll\t%0, 0x8\n\t" \ | ||
287 | "or\t%0, $1\n\t" \ | ||
288 | "4:lbu\t$1, 3(%2)\n\t" \ | ||
289 | "dsll\t%0, 0x8\n\t" \ | ||
290 | "or\t%0, $1\n\t" \ | ||
291 | "5:lbu\t$1, 4(%2)\n\t" \ | ||
292 | "dsll\t%0, 0x8\n\t" \ | ||
293 | "or\t%0, $1\n\t" \ | ||
294 | "6:lbu\t$1, 5(%2)\n\t" \ | ||
295 | "dsll\t%0, 0x8\n\t" \ | ||
296 | "or\t%0, $1\n\t" \ | ||
297 | "7:lbu\t$1, 6(%2)\n\t" \ | ||
298 | "dsll\t%0, 0x8\n\t" \ | ||
299 | "or\t%0, $1\n\t" \ | ||
300 | "8:lbu\t$1, 7(%2)\n\t" \ | ||
301 | "dsll\t%0, 0x8\n\t" \ | ||
302 | "or\t%0, $1\n\t" \ | ||
303 | "li\t%1, 0\n" \ | ||
304 | ".set\tpop\n\t" \ | ||
305 | "10:\n\t" \ | ||
306 | ".insn\n\t" \ | ||
307 | ".section\t.fixup,\"ax\"\n\t" \ | ||
308 | "11:\tli\t%1, %3\n\t" \ | ||
309 | "j\t10b\n\t" \ | ||
310 | ".previous\n\t" \ | ||
311 | ".section\t__ex_table,\"a\"\n\t" \ | ||
312 | STR(PTR)"\t1b, 11b\n\t" \ | ||
313 | STR(PTR)"\t2b, 11b\n\t" \ | ||
314 | STR(PTR)"\t3b, 11b\n\t" \ | ||
315 | STR(PTR)"\t4b, 11b\n\t" \ | ||
316 | STR(PTR)"\t5b, 11b\n\t" \ | ||
317 | STR(PTR)"\t6b, 11b\n\t" \ | ||
318 | STR(PTR)"\t7b, 11b\n\t" \ | ||
319 | STR(PTR)"\t8b, 11b\n\t" \ | ||
320 | ".previous" \ | ||
321 | : "=&r" (value), "=r" (res) \ | ||
322 | : "r" (addr), "i" (-EFAULT)); | ||
323 | #endif /* CONFIG_CPU_MIPSR6 */ | ||
324 | |||
209 | 325 | ||
210 | #define StoreHW(addr, value, res) \ | 326 | #define StoreHW(addr, value, res) \ |
211 | __asm__ __volatile__ ( \ | 327 | __asm__ __volatile__ ( \ |
@@ -228,6 +344,7 @@ extern void show_registers(struct pt_regs *regs); | |||
228 | : "=r" (res) \ | 344 | : "=r" (res) \ |
229 | : "r" (value), "r" (addr), "i" (-EFAULT)); | 345 | : "r" (value), "r" (addr), "i" (-EFAULT)); |
230 | 346 | ||
347 | #ifndef CONFIG_CPU_MIPSR6 | ||
231 | #define StoreW(addr, value, res) \ | 348 | #define StoreW(addr, value, res) \ |
232 | __asm__ __volatile__ ( \ | 349 | __asm__ __volatile__ ( \ |
233 | "1:\t"user_swl("%1", "(%2)")"\n" \ | 350 | "1:\t"user_swl("%1", "(%2)")"\n" \ |
@@ -263,9 +380,82 @@ extern void show_registers(struct pt_regs *regs); | |||
263 | ".previous" \ | 380 | ".previous" \ |
264 | : "=r" (res) \ | 381 | : "=r" (res) \ |
265 | : "r" (value), "r" (addr), "i" (-EFAULT)); | 382 | : "r" (value), "r" (addr), "i" (-EFAULT)); |
266 | #endif | 383 | #else |
384 | /* MIPSR6 has no swl and sdl instructions */ | ||
385 | #define StoreW(addr, value, res) \ | ||
386 | __asm__ __volatile__ ( \ | ||
387 | ".set\tpush\n\t" \ | ||
388 | ".set\tnoat\n\t" \ | ||
389 | "1:"user_sb("%1", "3(%2)")"\n\t" \ | ||
390 | "srl\t$1, %1, 0x8\n\t" \ | ||
391 | "2:"user_sb("$1", "2(%2)")"\n\t" \ | ||
392 | "srl\t$1, $1, 0x8\n\t" \ | ||
393 | "3:"user_sb("$1", "1(%2)")"\n\t" \ | ||
394 | "srl\t$1, $1, 0x8\n\t" \ | ||
395 | "4:"user_sb("$1", "0(%2)")"\n\t" \ | ||
396 | ".set\tpop\n\t" \ | ||
397 | "li\t%0, 0\n" \ | ||
398 | "10:\n\t" \ | ||
399 | ".insn\n\t" \ | ||
400 | ".section\t.fixup,\"ax\"\n\t" \ | ||
401 | "11:\tli\t%0, %3\n\t" \ | ||
402 | "j\t10b\n\t" \ | ||
403 | ".previous\n\t" \ | ||
404 | ".section\t__ex_table,\"a\"\n\t" \ | ||
405 | STR(PTR)"\t1b, 11b\n\t" \ | ||
406 | STR(PTR)"\t2b, 11b\n\t" \ | ||
407 | STR(PTR)"\t3b, 11b\n\t" \ | ||
408 | STR(PTR)"\t4b, 11b\n\t" \ | ||
409 | ".previous" \ | ||
410 | : "=&r" (res) \ | ||
411 | : "r" (value), "r" (addr), "i" (-EFAULT) \ | ||
412 | : "memory"); | ||
413 | |||
414 | #define StoreDW(addr, value, res) \ | ||
415 | __asm__ __volatile__ ( \ | ||
416 | ".set\tpush\n\t" \ | ||
417 | ".set\tnoat\n\t" \ | ||
418 | "1:sb\t%1, 7(%2)\n\t" \ | ||
419 | "dsrl\t$1, %1, 0x8\n\t" \ | ||
420 | "2:sb\t$1, 6(%2)\n\t" \ | ||
421 | "dsrl\t$1, $1, 0x8\n\t" \ | ||
422 | "3:sb\t$1, 5(%2)\n\t" \ | ||
423 | "dsrl\t$1, $1, 0x8\n\t" \ | ||
424 | "4:sb\t$1, 4(%2)\n\t" \ | ||
425 | "dsrl\t$1, $1, 0x8\n\t" \ | ||
426 | "5:sb\t$1, 3(%2)\n\t" \ | ||
427 | "dsrl\t$1, $1, 0x8\n\t" \ | ||
428 | "6:sb\t$1, 2(%2)\n\t" \ | ||
429 | "dsrl\t$1, $1, 0x8\n\t" \ | ||
430 | "7:sb\t$1, 1(%2)\n\t" \ | ||
431 | "dsrl\t$1, $1, 0x8\n\t" \ | ||
432 | "8:sb\t$1, 0(%2)\n\t" \ | ||
433 | "dsrl\t$1, $1, 0x8\n\t" \ | ||
434 | ".set\tpop\n\t" \ | ||
435 | "li\t%0, 0\n" \ | ||
436 | "10:\n\t" \ | ||
437 | ".insn\n\t" \ | ||
438 | ".section\t.fixup,\"ax\"\n\t" \ | ||
439 | "11:\tli\t%0, %3\n\t" \ | ||
440 | "j\t10b\n\t" \ | ||
441 | ".previous\n\t" \ | ||
442 | ".section\t__ex_table,\"a\"\n\t" \ | ||
443 | STR(PTR)"\t1b, 11b\n\t" \ | ||
444 | STR(PTR)"\t2b, 11b\n\t" \ | ||
445 | STR(PTR)"\t3b, 11b\n\t" \ | ||
446 | STR(PTR)"\t4b, 11b\n\t" \ | ||
447 | STR(PTR)"\t5b, 11b\n\t" \ | ||
448 | STR(PTR)"\t6b, 11b\n\t" \ | ||
449 | STR(PTR)"\t7b, 11b\n\t" \ | ||
450 | STR(PTR)"\t8b, 11b\n\t" \ | ||
451 | ".previous" \ | ||
452 | : "=&r" (res) \ | ||
453 | : "r" (value), "r" (addr), "i" (-EFAULT) \ | ||
454 | : "memory"); | ||
455 | #endif /* CONFIG_CPU_MIPSR6 */ | ||
456 | |||
457 | #else /* __BIG_ENDIAN */ | ||
267 | 458 | ||
268 | #ifdef __LITTLE_ENDIAN | ||
269 | #define LoadHW(addr, value, res) \ | 459 | #define LoadHW(addr, value, res) \ |
270 | __asm__ __volatile__ (".set\tnoat\n" \ | 460 | __asm__ __volatile__ (".set\tnoat\n" \ |
271 | "1:\t"user_lb("%0", "1(%2)")"\n" \ | 461 | "1:\t"user_lb("%0", "1(%2)")"\n" \ |
@@ -286,6 +476,7 @@ extern void show_registers(struct pt_regs *regs); | |||
286 | : "=&r" (value), "=r" (res) \ | 476 | : "=&r" (value), "=r" (res) \ |
287 | : "r" (addr), "i" (-EFAULT)); | 477 | : "r" (addr), "i" (-EFAULT)); |
288 | 478 | ||
479 | #ifndef CONFIG_CPU_MIPSR6 | ||
289 | #define LoadW(addr, value, res) \ | 480 | #define LoadW(addr, value, res) \ |
290 | __asm__ __volatile__ ( \ | 481 | __asm__ __volatile__ ( \ |
291 | "1:\t"user_lwl("%0", "3(%2)")"\n" \ | 482 | "1:\t"user_lwl("%0", "3(%2)")"\n" \ |
@@ -303,6 +494,40 @@ extern void show_registers(struct pt_regs *regs); | |||
303 | ".previous" \ | 494 | ".previous" \ |
304 | : "=&r" (value), "=r" (res) \ | 495 | : "=&r" (value), "=r" (res) \ |
305 | : "r" (addr), "i" (-EFAULT)); | 496 | : "r" (addr), "i" (-EFAULT)); |
497 | #else | ||
498 | /* MIPSR6 has no lwl instruction */ | ||
499 | #define LoadW(addr, value, res) \ | ||
500 | __asm__ __volatile__ ( \ | ||
501 | ".set\tpush\n" \ | ||
502 | ".set\tnoat\n\t" \ | ||
503 | "1:"user_lb("%0", "3(%2)")"\n\t" \ | ||
504 | "2:"user_lbu("$1", "2(%2)")"\n\t" \ | ||
505 | "sll\t%0, 0x8\n\t" \ | ||
506 | "or\t%0, $1\n\t" \ | ||
507 | "3:"user_lbu("$1", "1(%2)")"\n\t" \ | ||
508 | "sll\t%0, 0x8\n\t" \ | ||
509 | "or\t%0, $1\n\t" \ | ||
510 | "4:"user_lbu("$1", "0(%2)")"\n\t" \ | ||
511 | "sll\t%0, 0x8\n\t" \ | ||
512 | "or\t%0, $1\n\t" \ | ||
513 | "li\t%1, 0\n" \ | ||
514 | ".set\tpop\n" \ | ||
515 | "10:\n\t" \ | ||
516 | ".insn\n\t" \ | ||
517 | ".section\t.fixup,\"ax\"\n\t" \ | ||
518 | "11:\tli\t%1, %3\n\t" \ | ||
519 | "j\t10b\n\t" \ | ||
520 | ".previous\n\t" \ | ||
521 | ".section\t__ex_table,\"a\"\n\t" \ | ||
522 | STR(PTR)"\t1b, 11b\n\t" \ | ||
523 | STR(PTR)"\t2b, 11b\n\t" \ | ||
524 | STR(PTR)"\t3b, 11b\n\t" \ | ||
525 | STR(PTR)"\t4b, 11b\n\t" \ | ||
526 | ".previous" \ | ||
527 | : "=&r" (value), "=r" (res) \ | ||
528 | : "r" (addr), "i" (-EFAULT)); | ||
529 | #endif /* CONFIG_CPU_MIPSR6 */ | ||
530 | |||
306 | 531 | ||
307 | #define LoadHWU(addr, value, res) \ | 532 | #define LoadHWU(addr, value, res) \ |
308 | __asm__ __volatile__ ( \ | 533 | __asm__ __volatile__ ( \ |
@@ -326,6 +551,7 @@ extern void show_registers(struct pt_regs *regs); | |||
326 | : "=&r" (value), "=r" (res) \ | 551 | : "=&r" (value), "=r" (res) \ |
327 | : "r" (addr), "i" (-EFAULT)); | 552 | : "r" (addr), "i" (-EFAULT)); |
328 | 553 | ||
554 | #ifndef CONFIG_CPU_MIPSR6 | ||
329 | #define LoadWU(addr, value, res) \ | 555 | #define LoadWU(addr, value, res) \ |
330 | __asm__ __volatile__ ( \ | 556 | __asm__ __volatile__ ( \ |
331 | "1:\t"user_lwl("%0", "3(%2)")"\n" \ | 557 | "1:\t"user_lwl("%0", "3(%2)")"\n" \ |
@@ -363,6 +589,86 @@ extern void show_registers(struct pt_regs *regs); | |||
363 | ".previous" \ | 589 | ".previous" \ |
364 | : "=&r" (value), "=r" (res) \ | 590 | : "=&r" (value), "=r" (res) \ |
365 | : "r" (addr), "i" (-EFAULT)); | 591 | : "r" (addr), "i" (-EFAULT)); |
592 | #else | ||
593 | /* MIPSR6 has not lwl and ldl instructions */ | ||
594 | #define LoadWU(addr, value, res) \ | ||
595 | __asm__ __volatile__ ( \ | ||
596 | ".set\tpush\n\t" \ | ||
597 | ".set\tnoat\n\t" \ | ||
598 | "1:"user_lbu("%0", "3(%2)")"\n\t" \ | ||
599 | "2:"user_lbu("$1", "2(%2)")"\n\t" \ | ||
600 | "sll\t%0, 0x8\n\t" \ | ||
601 | "or\t%0, $1\n\t" \ | ||
602 | "3:"user_lbu("$1", "1(%2)")"\n\t" \ | ||
603 | "sll\t%0, 0x8\n\t" \ | ||
604 | "or\t%0, $1\n\t" \ | ||
605 | "4:"user_lbu("$1", "0(%2)")"\n\t" \ | ||
606 | "sll\t%0, 0x8\n\t" \ | ||
607 | "or\t%0, $1\n\t" \ | ||
608 | "li\t%1, 0\n" \ | ||
609 | ".set\tpop\n" \ | ||
610 | "10:\n\t" \ | ||
611 | ".insn\n\t" \ | ||
612 | ".section\t.fixup,\"ax\"\n\t" \ | ||
613 | "11:\tli\t%1, %3\n\t" \ | ||
614 | "j\t10b\n\t" \ | ||
615 | ".previous\n\t" \ | ||
616 | ".section\t__ex_table,\"a\"\n\t" \ | ||
617 | STR(PTR)"\t1b, 11b\n\t" \ | ||
618 | STR(PTR)"\t2b, 11b\n\t" \ | ||
619 | STR(PTR)"\t3b, 11b\n\t" \ | ||
620 | STR(PTR)"\t4b, 11b\n\t" \ | ||
621 | ".previous" \ | ||
622 | : "=&r" (value), "=r" (res) \ | ||
623 | : "r" (addr), "i" (-EFAULT)); | ||
624 | |||
625 | #define LoadDW(addr, value, res) \ | ||
626 | __asm__ __volatile__ ( \ | ||
627 | ".set\tpush\n\t" \ | ||
628 | ".set\tnoat\n\t" \ | ||
629 | "1:lb\t%0, 7(%2)\n\t" \ | ||
630 | "2:lbu\t$1, 6(%2)\n\t" \ | ||
631 | "dsll\t%0, 0x8\n\t" \ | ||
632 | "or\t%0, $1\n\t" \ | ||
633 | "3:lbu\t$1, 5(%2)\n\t" \ | ||
634 | "dsll\t%0, 0x8\n\t" \ | ||
635 | "or\t%0, $1\n\t" \ | ||
636 | "4:lbu\t$1, 4(%2)\n\t" \ | ||
637 | "dsll\t%0, 0x8\n\t" \ | ||
638 | "or\t%0, $1\n\t" \ | ||
639 | "5:lbu\t$1, 3(%2)\n\t" \ | ||
640 | "dsll\t%0, 0x8\n\t" \ | ||
641 | "or\t%0, $1\n\t" \ | ||
642 | "6:lbu\t$1, 2(%2)\n\t" \ | ||
643 | "dsll\t%0, 0x8\n\t" \ | ||
644 | "or\t%0, $1\n\t" \ | ||
645 | "7:lbu\t$1, 1(%2)\n\t" \ | ||
646 | "dsll\t%0, 0x8\n\t" \ | ||
647 | "or\t%0, $1\n\t" \ | ||
648 | "8:lbu\t$1, 0(%2)\n\t" \ | ||
649 | "dsll\t%0, 0x8\n\t" \ | ||
650 | "or\t%0, $1\n\t" \ | ||
651 | "li\t%1, 0\n" \ | ||
652 | ".set\tpop\n\t" \ | ||
653 | "10:\n\t" \ | ||
654 | ".insn\n\t" \ | ||
655 | ".section\t.fixup,\"ax\"\n\t" \ | ||
656 | "11:\tli\t%1, %3\n\t" \ | ||
657 | "j\t10b\n\t" \ | ||
658 | ".previous\n\t" \ | ||
659 | ".section\t__ex_table,\"a\"\n\t" \ | ||
660 | STR(PTR)"\t1b, 11b\n\t" \ | ||
661 | STR(PTR)"\t2b, 11b\n\t" \ | ||
662 | STR(PTR)"\t3b, 11b\n\t" \ | ||
663 | STR(PTR)"\t4b, 11b\n\t" \ | ||
664 | STR(PTR)"\t5b, 11b\n\t" \ | ||
665 | STR(PTR)"\t6b, 11b\n\t" \ | ||
666 | STR(PTR)"\t7b, 11b\n\t" \ | ||
667 | STR(PTR)"\t8b, 11b\n\t" \ | ||
668 | ".previous" \ | ||
669 | : "=&r" (value), "=r" (res) \ | ||
670 | : "r" (addr), "i" (-EFAULT)); | ||
671 | #endif /* CONFIG_CPU_MIPSR6 */ | ||
366 | 672 | ||
367 | #define StoreHW(addr, value, res) \ | 673 | #define StoreHW(addr, value, res) \ |
368 | __asm__ __volatile__ ( \ | 674 | __asm__ __volatile__ ( \ |
@@ -384,7 +690,7 @@ extern void show_registers(struct pt_regs *regs); | |||
384 | ".previous" \ | 690 | ".previous" \ |
385 | : "=r" (res) \ | 691 | : "=r" (res) \ |
386 | : "r" (value), "r" (addr), "i" (-EFAULT)); | 692 | : "r" (value), "r" (addr), "i" (-EFAULT)); |
387 | 693 | #ifndef CONFIG_CPU_MIPSR6 | |
388 | #define StoreW(addr, value, res) \ | 694 | #define StoreW(addr, value, res) \ |
389 | __asm__ __volatile__ ( \ | 695 | __asm__ __volatile__ ( \ |
390 | "1:\t"user_swl("%1", "3(%2)")"\n" \ | 696 | "1:\t"user_swl("%1", "3(%2)")"\n" \ |
@@ -420,6 +726,79 @@ extern void show_registers(struct pt_regs *regs); | |||
420 | ".previous" \ | 726 | ".previous" \ |
421 | : "=r" (res) \ | 727 | : "=r" (res) \ |
422 | : "r" (value), "r" (addr), "i" (-EFAULT)); | 728 | : "r" (value), "r" (addr), "i" (-EFAULT)); |
729 | #else | ||
730 | /* MIPSR6 has no swl and sdl instructions */ | ||
731 | #define StoreW(addr, value, res) \ | ||
732 | __asm__ __volatile__ ( \ | ||
733 | ".set\tpush\n\t" \ | ||
734 | ".set\tnoat\n\t" \ | ||
735 | "1:"user_sb("%1", "0(%2)")"\n\t" \ | ||
736 | "srl\t$1, %1, 0x8\n\t" \ | ||
737 | "2:"user_sb("$1", "1(%2)")"\n\t" \ | ||
738 | "srl\t$1, $1, 0x8\n\t" \ | ||
739 | "3:"user_sb("$1", "2(%2)")"\n\t" \ | ||
740 | "srl\t$1, $1, 0x8\n\t" \ | ||
741 | "4:"user_sb("$1", "3(%2)")"\n\t" \ | ||
742 | ".set\tpop\n\t" \ | ||
743 | "li\t%0, 0\n" \ | ||
744 | "10:\n\t" \ | ||
745 | ".insn\n\t" \ | ||
746 | ".section\t.fixup,\"ax\"\n\t" \ | ||
747 | "11:\tli\t%0, %3\n\t" \ | ||
748 | "j\t10b\n\t" \ | ||
749 | ".previous\n\t" \ | ||
750 | ".section\t__ex_table,\"a\"\n\t" \ | ||
751 | STR(PTR)"\t1b, 11b\n\t" \ | ||
752 | STR(PTR)"\t2b, 11b\n\t" \ | ||
753 | STR(PTR)"\t3b, 11b\n\t" \ | ||
754 | STR(PTR)"\t4b, 11b\n\t" \ | ||
755 | ".previous" \ | ||
756 | : "=&r" (res) \ | ||
757 | : "r" (value), "r" (addr), "i" (-EFAULT) \ | ||
758 | : "memory"); | ||
759 | |||
760 | #define StoreDW(addr, value, res) \ | ||
761 | __asm__ __volatile__ ( \ | ||
762 | ".set\tpush\n\t" \ | ||
763 | ".set\tnoat\n\t" \ | ||
764 | "1:sb\t%1, 0(%2)\n\t" \ | ||
765 | "dsrl\t$1, %1, 0x8\n\t" \ | ||
766 | "2:sb\t$1, 1(%2)\n\t" \ | ||
767 | "dsrl\t$1, $1, 0x8\n\t" \ | ||
768 | "3:sb\t$1, 2(%2)\n\t" \ | ||
769 | "dsrl\t$1, $1, 0x8\n\t" \ | ||
770 | "4:sb\t$1, 3(%2)\n\t" \ | ||
771 | "dsrl\t$1, $1, 0x8\n\t" \ | ||
772 | "5:sb\t$1, 4(%2)\n\t" \ | ||
773 | "dsrl\t$1, $1, 0x8\n\t" \ | ||
774 | "6:sb\t$1, 5(%2)\n\t" \ | ||
775 | "dsrl\t$1, $1, 0x8\n\t" \ | ||
776 | "7:sb\t$1, 6(%2)\n\t" \ | ||
777 | "dsrl\t$1, $1, 0x8\n\t" \ | ||
778 | "8:sb\t$1, 7(%2)\n\t" \ | ||
779 | "dsrl\t$1, $1, 0x8\n\t" \ | ||
780 | ".set\tpop\n\t" \ | ||
781 | "li\t%0, 0\n" \ | ||
782 | "10:\n\t" \ | ||
783 | ".insn\n\t" \ | ||
784 | ".section\t.fixup,\"ax\"\n\t" \ | ||
785 | "11:\tli\t%0, %3\n\t" \ | ||
786 | "j\t10b\n\t" \ | ||
787 | ".previous\n\t" \ | ||
788 | ".section\t__ex_table,\"a\"\n\t" \ | ||
789 | STR(PTR)"\t1b, 11b\n\t" \ | ||
790 | STR(PTR)"\t2b, 11b\n\t" \ | ||
791 | STR(PTR)"\t3b, 11b\n\t" \ | ||
792 | STR(PTR)"\t4b, 11b\n\t" \ | ||
793 | STR(PTR)"\t5b, 11b\n\t" \ | ||
794 | STR(PTR)"\t6b, 11b\n\t" \ | ||
795 | STR(PTR)"\t7b, 11b\n\t" \ | ||
796 | STR(PTR)"\t8b, 11b\n\t" \ | ||
797 | ".previous" \ | ||
798 | : "=&r" (res) \ | ||
799 | : "r" (value), "r" (addr), "i" (-EFAULT) \ | ||
800 | : "memory"); | ||
801 | #endif /* CONFIG_CPU_MIPSR6 */ | ||
423 | #endif | 802 | #endif |
424 | 803 | ||
425 | static void emulate_load_store_insn(struct pt_regs *regs, | 804 | static void emulate_load_store_insn(struct pt_regs *regs, |
@@ -703,10 +1082,13 @@ static void emulate_load_store_insn(struct pt_regs *regs, | |||
703 | break; | 1082 | break; |
704 | return; | 1083 | return; |
705 | 1084 | ||
1085 | #ifndef CONFIG_CPU_MIPSR6 | ||
706 | /* | 1086 | /* |
707 | * COP2 is available to implementor for application specific use. | 1087 | * COP2 is available to implementor for application specific use. |
708 | * It's up to applications to register a notifier chain and do | 1088 | * It's up to applications to register a notifier chain and do |
709 | * whatever they have to do, including possible sending of signals. | 1089 | * whatever they have to do, including possible sending of signals. |
1090 | * | ||
1091 | * This instruction has been reallocated in Release 6 | ||
710 | */ | 1092 | */ |
711 | case lwc2_op: | 1093 | case lwc2_op: |
712 | cu2_notifier_call_chain(CU2_LWC2_OP, regs); | 1094 | cu2_notifier_call_chain(CU2_LWC2_OP, regs); |
@@ -723,7 +1105,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, | |||
723 | case sdc2_op: | 1105 | case sdc2_op: |
724 | cu2_notifier_call_chain(CU2_SDC2_OP, regs); | 1106 | cu2_notifier_call_chain(CU2_SDC2_OP, regs); |
725 | break; | 1107 | break; |
726 | 1108 | #endif | |
727 | default: | 1109 | default: |
728 | /* | 1110 | /* |
729 | * Pheeee... We encountered an yet unknown instruction or | 1111 | * Pheeee... We encountered an yet unknown instruction or |